PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Lichtsensoren Auswerten



petzi--
21.06.2012, 15:00
Hallo zusammen ,
nachdem ich meinen RP6 mit einem Roboterarm ausgerüstet habe möchte ich nun eine automatische Beleuchtung anbringen
starke LEDs hab ich schon , Ich möchte das Programm so schreiben , dass wenn die Lichtsensoren des RP6 eine Lichtstärke messen die eine Bestimmte Helligkeit unterschreitet der RP6 eine seiner LEDs anschaltet und somit auch den dazugehörigen I/O Port an den ich einen Transistor hänge der dann meine LEDs eischaltet

in etwa so

if(festgelegter Minimallichtwer)
{
setLEDs(0b010000);
}

schonmal Danke...

Max Web
21.06.2012, 16:09
Hallo,

die Werte der Lichtsensoren des RP6 fragst Du mit adcLSL und adcLSR ab.
Jedoch würde ich Dir nicht empfehlen, die Beleuchtung mit nur einem Schwellwert zu steuern:
Nehmen wir mal an, dass der gemessene Lichtwert ständig um den Schwellwert pendelt. Das würde bedeuten, dass Deine Beleuchtung ständig ein- und ausgeschaltet wird - das sieht ziemlich unprofessionell aus ;)
Stattdessen solltest Du eine Hysterese (zwei Schwellwerte) einführen. Das bedeutet, dass Du die Lichter einschaltest, wenn ein Schwellwert SCHWELLWERT_AUS unterschritten wird und sie erst wieder einschaltest, wenn Schwellwert
SCHWELLWERT_EIN überschritten wird, wobei natürlich SCHWELLWERT_EIN>SCHWELLWERT_AUS gilt. SCHWELLWERT_AUS und SCHWELLWERT_EIN musst Du experimentell bestimmen - einfach so, wie es Dir gefällt ;)

In Pseudocode sieht das so aus:



#define SCHWELLWERT_AUS ...
#define SCHWELLWERT_EIN ...

...
...
...

if(adcLSL<= SCHWELLWERT_AUS){ //Schwellwert für "Licht aus" wurde unterschritten
setLEDs(...);//Mach die Lichter aus
}else if(adcLSL >= SCHWELLWERT_EIN){ //Schwellwert für "Licht ein" wurde überschritten
setLEDs(...);//Schalte sie hier wieder ein
}

Grüße,

Max

petzi--
21.06.2012, 17:01
Danke ,
ich hab mal etwas einfacher angefangen, aber iregend etwas fonktioniert da nicht richtet :(

Mein Programm:


#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
powerON();

while(true)
{
task_RP6System();

if(adcLSL<= 200)
{
setLEDs(0b010000);
}
}
return 0;
}


Gruß,
petzi--

Max Web
21.06.2012, 17:28
Hallo,

also, wenn ich das richtig verstehe hast Du den Transistor, der Deine Beleuchtung ansteuert, direkt an den LED Pin 5 angeschlossen?
Leuchtet denn die LED 5 am RP6, wenn Du das Programm ausführst und den linken Lichtsensor bedeckst? Lass Dir auch mal die Sensorwerte per RP6Loader ausgeben (WriteInteger und WriteString_P verwenden).
Vielleicht ist hier auch einfach etwas falsch verschaltet, bitte prüfe das nochmal! Probiere es auch mal mit abgeklemmtem Transistor.
Und: was genau funktioniert nicht?

Max

radbruch
21.06.2012, 17:29
Hallo

Mal aus der Hüfte geschossen: adcLSL wird durch das Tasksystem mit dem Helligkeitswert geladen:


/**
* This functions checks all ADC channels sequentially in the Background!
* It can save a lot of time, if the ADC channels are checked like this, because
* each A/D conversion takes some time. With this function you don't need to
* wait until the A/D conversion is finished and you can do other things in the
* meanwhile.
* If you use this function (this is also the case if you use task_RP6System
* because it calls this function), you can NOT use readADC anymore!
*
* Instead you can use the seven global variables you see above to
* get the ADC values!
*/
void task_ADC(void)
{
static uint8_t current_adc_channel = 0;
if(!(ADCSRA & (1<<ADSC))) {
// ADCSRA |= (1<<ADIF);
switch(current_adc_channel) {
case 0: adcBat = ADC; startADC(ADC_MCURRENT_L); break;
case 1: adcMotorCurrentLeft = ADC; startADC(ADC_MCURRENT_R); break;
case 2: adcMotorCurrentRight = ADC; startADC(ADC_LS_L); break;
case 3: adcLSL = ADC; startADC(ADC_LS_R); break;
case 4: adcLSR = ADC; startADC(ADC_ADC0); break;
case 5: adc0 = ADC; startADC(ADC_ADC1); break;
case 6: adc1 = ADC; startADC(ADC_BAT); break;
}
if(current_adc_channel == 6)
current_adc_channel = 0;
else
current_adc_channel++;
}
}Wenn du das Tasksystem vorerst nicht verwenden möchtest, dann kannst du die Werte auch mit readADC() ermitteln:


/************************************************** ***************************/
// ADC:

/**
* Read ADC channel (10 bit -> result is an integer from 0 to 1023).
* The channels (ADC_BAT etc.) are defined in the RP6RobotBase.h file!
*
* This is a blocking function, which means it waits until the conversion
* is complete. There is a more complicated alternative that frequently
* checks all channels (s. below).
*
* This function returns 0 if the ADC is buisy! This has been done to
* prevents problems when the automatical function is used.
* You should usually NOT use this function if you use the automatic one!
*
* Example:
*
* uint16_t uBat = readADC(ADC_BAT);
* if(uBat < 600)
* writeString("WARNING: BAT IS LOW!\n");
*
*/
uint16_t readADC(uint8_t channel)
{
if((ADCSRA & (1<<ADSC))) return 0; // check if ADC is buisy...
ADMUX = (1<<REFS0) | (0<<REFS1) | (channel<<MUX0);
ADCSRA = (0<<ADIE) | (1<<ADSC) | (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADIF);
while ((ADCSRA & (1<<ADSC)));
ADCSRA |= (1<<ADIF);
return ADC;
}
(Beide Funktionen sind aus RP6RobotBaseLib.c)

Die Kanäle werden in RP6RobotBase.h definiert:

#define ADC_BAT 7
#define ADC_MCURRENT_L 6
#define ADC_MCURRENT_R 5
#define ADC_LS_L 3
#define ADC_LS_R 2
#define ADC_ADC1 1
#define ADC_ADC0 0



Gruß

mic

petzi--
21.06.2012, 20:35
Danke für die vielen Antworten :),
Ich hab das Problem jetzt so gelöst:


#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
powerON();

while(true)
{
task_RP6System();

if(adcLSL>=520)
{
setLEDs(0b000000);
}

else
{
setLEDs(0b000100);
}
}

return 0;
}

Gruß,
petzi--