PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pogramierschierigkeiten



efbrgn
05.03.2008, 10:44
Hi ich habe zu Weihnachten den Robby Rp6gekriegt:)
aber hatte in letzter Zeit nicht soviel Zeit dafür sodass ich letzte Woche mal angefangen habe ein kleines Programm zu schreiben und zwar will ich ein bischen mit dem Robby über die serielle Schnittstelle reden.
So an einer Stelle hake ich jetzt. Und zwar will ich, dass wenn der Lichtsensor 1000oder höher ist soll er sagen, dass es ihm zu hell ist. Bei unter 400 soll er mir sagen, dass ich das Licht anmachen soll:).
Ich hatte das auch hingekriegt, allerding hat er mir alle 100ms gesagt wie das Licht gerade ist.Ich will aber, dass er sich nur meldet wenn sich das Licht verändert...
Ich habe es nochmal neu versucht aber so eine richtige Idee habe ich nicht:(.



include "RP6RobotBaseLib.h"


void outputTextStuff(void)
{
writeString_P("\nGuten Tach, ich bin der Robby");
light();


}


void light(void)
{
if(adcLSR<400)
{
writeString_P("\nMach das Licht an!\n");
}
else if((adcLSR<1000)&&(adcLSR>400))
{
writeString_P("\nDie Lichtverhältnisse hier sind wirklich gut. So lässt es sich Leben:)!\n");
}
else
{
writeString_P("\nMir ist es hier zu hell!\n");
}
}



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


while(true)
{
task_ADC();
}

return 0;
}


Soweit bin ich jetzt allerdings sagt der mir jetzt nur einmal ob ich das Licht anmachen soll:(.
Vielleicht kann mir ja jemand helfen...
mfg efbrgn

KayH
05.03.2008, 11:50
Hi,

die light() methode gehoert in die while(true){} Schleife.
Zusaetzlich musst Du den Wert des ADC in eine Variable speichern. Dann mit letztem Speicherwert vergleichen. Wenn sich der Zustand geaendert hat, Meldung ausgeben und den Wert neu speichern, andernfalls nichts tun ...

hth
Kay

efbrgn
05.03.2008, 12:14
da gibt es aber noch ein Problem und zwar soll dass ja nicht geschrieben werden, wenn der Wert sich ändert, sondern nur wann er die 100 bzw. 400er Marke überschreitet.Ist das auch möglich??

Gock
05.03.2008, 13:08
Kay hat schon recht. Wenn Du den Aufruf der Funktion richtigerweise in die while-Schleife schreibst, würde er unentwegt seinen Text senden. Das willst Du ja nicht, oder? Es reicht ja, wenn er es einmal bei jeder Über- bzw. Unterschreitung tut.
Anderenfalls müsstest Du den Aufruf mit einem Timer auslösen.
Gruß

efbrgn
05.03.2008, 13:35
Kay hat schon recht. Wenn Du den Aufruf der Funktion richtigerweise in die while-Schleife schreibst, würde er unentwegt seinen Text senden. Das willst Du ja nicht, oder? Es reicht ja, wenn er es einmal bei jeder Über- bzw. Unterschreitung tut.


genauso will ich das machen, aber wie mache ich das???
nach der Art und Weise von Kay würde er ja bei jeder Abweichung das Lichtsensor etwas melden, und das wäre ja alle paar Selunden. Aber er soll es nur bei ganz besimmten Punkte medlen(400,100). Und habe ich keine Idee wie man das machen könnte.
mfg efbrgn

blenderkid
05.03.2008, 13:44
hi,



include "RP6RobotBaseLib.h"


void outputTextStuff(last)
{
writeString_P("\nGuten Tach, ich bin der Robby");
light(last);


}


void light(last)
{

if(adcLSR<400 && last > 400)
{
writeString_P("\nMach das Licht an!\n");
}
else if(((adcLSR<1000)&&(adcLSR>400)) && ((last <400) && last > 1000)))
{
writeString_P("\nDie Lichtverhältnisse hier sind wirklich gut. So lässt es sich Leben:)!\n");
}
if (adcLSR>1000 && last < 1000)
{
writeString_P("\nMir ist es hier zu hell!\n");
}
last = adcLSR;
}



int main (void)
{
initRobotBase();
uint16_t last;
outputTextStuff(last);

startStopwatch1();
while(true)
{

task_ADC();
if (getStopwatch() > 100)
{
outputTextStuff(last);
setStopwatch(0);
}
}

return 0;
}



So in etwa müsste es funktionieren, habe den Code aber nicht getestet.
Ich habe eine Stopwatch verwendet, damit, wenn sie auf 100 ist die abfrage erfolgt, jetzt wird getestet ob "last" anders ist als adcLSR und den rest habe ich von dir übernommen.


MfG blenderkid[/code]

blenderkid
05.03.2008, 13:49
uups jetzt habe ich ne neue Frage gfunden, habe das mit dem (100,400 ) nicht gesehen, also du möchtest ,dass er nur neu misst wenn es dunkler wird?
Nicht wenn es sich ins helle verwandelt?

efbrgn
05.03.2008, 13:52
ne nicht ganz, er soll schon messen, die ganze Zeit immer. Aber er soll mir dass nua sagen wenn seine Werte 400unterschreiten oder 1000überschreiten... und dann auch nua einmal und ich 10mal in der Sekunde:)

blenderkid
05.03.2008, 13:54
ok dann is mein code eig richtig.

zerush
05.03.2008, 13:55
Wen du einfach den Zustand speicherst (also genau richtig, zu hell, zu dunkel), kannst du einfach überprüfen, ob dieser sich geändert hat. Wenn dies der Fall ist, gibst du die entsprechende Meldung aus.

Beispiel:



unsigned char brightOld = 0;
void light(void){

unsigned char bright;

if(adcLSR<400){
bright = 1;
}
else if((adcLSR<1000)&&(adcLSR>400)){
bright = 0;
}
else{
bright = 2;
}

if(bright != brightOld){
switch(bright){
case 0:
writeString_P("\nDie Lichtverhältnisse hier sind wirklich gut. So lässt es sich Leben:)!\n");
break;
case 1:
writeString_P("\nMach das Licht an!\n");
break;
case 2:
writeString_P("\nMir ist es hier zu hell!\n");
break;
}
}

brightOld = bright;

}


Die müsste dann aus der while-Schleife aufgerufen werden.

mfg
zerush

EDIT: sorry, hab jetzt ers gesehn, dass schon soviele neuen Antworten kamen... naja aber mehrere Möglichkeiten schaden ja nicht ;)

blenderkid
05.03.2008, 13:58
jetzt hat man aber noch einpaar Zeilen mehr Code

Ups hab das EDIT nicht gesehen.

zerush
05.03.2008, 14:01
Ja,
ist aber überschaubarer finde ich.
Und als compilierter Code wird es sogar weniger sein, weil es weniger Vergleiche sind.

Gruß
zerush

blenderkid
05.03.2008, 14:03
ja ok, is gut mit mehreren Möglichkeiten, das mit dem Compiler wusste ich noch nicht.

efbrgn
05.03.2008, 14:28
dankeschön das funzt =P~ =P~
ich glaube ich verstehe sogar was du da gemacht hast :)

efbrgn
05.03.2008, 14:44
ok irgendwas ist da doch komisch.wenn ich mein das Lichts ausmachen und dann wieder an, sagt er beim anmchen nochmal mach das Licht an.
Und wann ich das ganz oft mache sagt er manchmal auch:"Mit ist es zu hell!"obwohl er niemals den Wert 1000erreicht hat.

zerush
05.03.2008, 15:33
poste doch nochmal den kompletten code so wie du ihn nun verwendest...

efbrgn
05.03.2008, 15:36
#include "RP6RobotBaseLib.h"



unsigned char brightOld = 0;
void light(void){

unsigned char bright;

if(adcLSR<400){
bright = 1;
}
else if((adcLSR<1000)&&(adcLSR>400)){
bright = 0;
}
else if (adcLSR>1000){
bright = 2;
}

if(bright != brightOld){
switch(bright){
case 0:
break;
case 1:
writeString_P("\nMach das Licht an!\n");
break;
case 2:
writeString_P("\nMir ist es hier zu hell!\n");
break;
}

}

brightOld = bright;

}
void main (void)
{
initRobotBase();


while(true)
{
task_ADC();
light();
}
return 0;
}



wenn man z.B. immer mit Finger ganz schnell drüberfährt, sagt er auch einmal es ist zu hell, obwohl der Raum dunkel ist:(
[/code]

zerush
05.03.2008, 15:58
Du kannst dir ja testweise einfach mal die Werte ausgeben lassen, die er misst...
Dann kann man dann schauen wo der Fehler liegt.

efbrgn
05.03.2008, 16:23
Wenn ich eine Lampe davor halte, wo Ergebnisse normalweise von über 1000 erscheinen. Steht da immer
Mach das Licht an.
Mir ist es zu hell!!
Mach das Licht an.
Mir ist es zu hell!!
Mach das Licht an.
Mir ist es zu hell!!
Mach das Licht an.
Mir ist es zu hell!!
Mach das Licht an.
Mir ist es zu hell!!
Mach das Licht an.
Mir ist es zu hell!!
Mach das Licht an.
Mir ist es zu hell!!
Mach das Licht an.
Mir ist es zu hell!!
und das so 100mal pro sekunde...
und das wollte ich eigentlich nicht:(




wenns zu dunkel ist klappt das alles wunderbar, nur mit der Helligkeit komt er irgendwie nicht zurecht...

Pr0gm4n
05.03.2008, 18:33
setz doch mal die Grenze auf 1200 bzw. wenn er dann bei der Taschenlampe nicht mehr anspringt auf 1100 oder so...


wenn es dann gehen sollte, dann iss die messung mit der lampe ganz nah an 1000 dran bzw. es schwankt leicht und du erhältst genau das Resultat


MfG Pr0gm4n

radbruch
05.03.2008, 19:38
Hallo


#include "RP6RobotBaseLib.h"



unsigned char brightOld = 0;
unsigned char bright = 0;

void light(void){


if(adcLSR<400){
bright = 1;
}
else if((adcLSR<=1000)&&(adcLSR>=400)){
bright = 0;
}
else if (adcLSR>1000){
bright = 2;
}

if(bright != brightOld){
switch(bright){
case 0:
writeString_P("\nIch bin glücklich\n");
break;
case 1:
writeString_P("\nMach das Licht an!\n");
break;
case 2:
writeString_P("\nMir ist es hier zu hell!\n");
break;
}

}

brightOld = bright;

}
int main (void)
{
initRobotBase();


while(true)
{
task_ADC();
light();
}
return 0;
}
Das Problem war die lokale Variable bright die nicht initialisiert wurde. Bei jedem Aufruf von light() wurde sie neu angelegt und hatte dann den zufälligen Wert, der im Speicher stand.

Für bright==0 habe ich noch eine Meldung eingefügt damit man merkt, wenn sich die Helligkeit ändert. Die Abfrage zum Setzen von bright=0 habe ich um <= bzw. >= erweitert.

Mit dem adc-Task wird nur bei jedem 6sten Aufruf ein neuer Wert in adcLSR gespeichert:


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++;
}
}


Das könnte man berücksichtigen und in light() zuerst prüfen, ob sich adcLSR seit dem letzen Aufruf geändert hat.

Übrigens hat der Mega32 reichlich Speicher, den könnt ihr mit den paar Programmzeilen nie füllen ;) Nettes Programm..

Gruß

mic

PcVirus
05.03.2008, 19:43
Probier es mal so: (nicht getestet)



void light(void)
{
#define LICHT_AN 0
#define LICHT_OK 1
#define LICHT_AUS 2

static uint8_t old = 0;
if(adcLSR<400 && old != LICHT_AN)
{
writeString_P("\nMach das Licht an!\n");
old = LICHT_AN;
}
else if((adcLSR<1000)&&(adcLSR>400)&&old != LICHT_OK)
{
writeString_P("\nDie Lichtverhältnisse hier sind wirklich gut. So lässt es sich Leben:)!\n");
old = LICHT_OK;
}
else if(old != LICHT_AUS)
{
writeString_P("\nMir ist es hier zu hell!\n");
old = LICHT_AUS;
}
}

efbrgn
06.03.2008, 10:39
So danke erstmal für eure ganzen Vorschläge...
ich habe sie alle ausprobiert und habe mir daraus selber ein Prog geschreiben weil die alle so ihre Tücken hatten:):)Als Vorlage habe ich mir das von zerush genommen, weil das eig. das einzige wa wo ich verstanden habe was er gemacht hat:):).
So eine Tücke hat das aber noch, und zwar schreibt er am Anfang immer mir ist es zu dunkel...
Also ich habe gesagt dass er mir aufschreiben soll wie das Licht ist und siehe da, im ersten durchganz wir immer 0 gemessen. Könnte man das vielleicht so machen, dass er im ersten Durchgang noch nicht aufschreibt???




#include "RP6RobotBaseLib.h"


unsigned char brightOld=0;
unsigned char bright=0;

void light(void){

writeIntegerLength(brightOld, DEC, 1);
writeIntegerLength(bright, DEC, 1);
writeIntegerLength(adcLSR, DEC, 4);


if(adcLSR<=400){
bright = 1;
}
else if((adcLSR<1000)&&(adcLSR>400)){
bright = 0;
}
else if (adcLSR>=1000){
bright = 2;
}

if(bright != brightOld){
switch(bright){
case 0:
break;
case 1:
writeString_P("\nMach das Licht an!\n");
mSleep(1000);
break;
case 2:
writeString_P("\nMir ist es hier zu hell!\n");
mSleep(1000);
break;

}
brightOld=bright;

}

}
void main (void)
{

initRobotBase();


while(true)
{
task_ADC();
light();

}
return 0;
}

KayH
06.03.2008, 12:44
Hi,

ich hab mit Absicht nicht alles haarklein beschrieben (oder sourcecode gepostet). Dann bleibt fuer Dich auch ein Aha-Erlebnis. Mit dem lernt man viel besser als fertigen code zu verwenden.
Nun sieht es ja schon ganz ordentlich aus. :-) Anstelle des "case 0" wuerde ich allerding "default" im switch verwenden.

Als Ergaenzung: das hier gezeigte geht in Richtung FSM (finite state machine). So kann man z.B. auch Taster softwaretechnisch entprellen. Und natuerlich noch viele andere tolle Dinge tun... :-)

efbrgn
06.03.2008, 13:56
was heißt den einen Taster softwaretechnisch entprellen...
und zu meiner Frage hat da vielleicht noch wer ne idee??

zerush
06.03.2008, 14:44
Wie radbruch ja festgestellt hat, aktualisiert die taskADC() Funktion den gewünschten Wert nur bei jedem 6ten Mal...

Rufe doch einfach in einer for-Schleife die taskADC() 6 mal hintereinander auf.
Das sollte den ersten dunklen Messwert eliminieren.

efbrgn
06.03.2008, 14:58
ne das geht nicht, aber ich habe mal Radbruches Variante versucht, versteh zwar net was er da macht aber egal....
allerdings sagt der zur letzten Zeile_"expectet declaration or statement of the end of input"....ich weiß jetzt nicht genau was er da von mir will!!!


#include "RP6RobotBaseLib.h"


unsigned char brightOld=0;
unsigned char bright=0;

void light(void){

writeIntegerLength(brightOld, DEC, 1);
writeIntegerLength(bright, DEC, 1);
writeIntegerLength(adcLSR, DEC, 4);

if(adcLSR<=400){
bright = 1;
}
else if((adcLSR<1000)&&(adcLSR>400)){
bright = 0;
}
else if (adcLSR>=1000){
bright = 2;
}

if(bright != brightOld){
switch(bright){
case 0:
writeString_P("\nSchon bessa:)!!\n");
break;
case 1:
writeString_P("\nMach das Licht an!\n");
mSleep(1000);
break;
case 2:
writeString_P("\nMir ist es hier zu hell!\n");
mSleep(1000);
break;

}
brightOld=bright;

}

}
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++;
}
void main (void)
{

initRobotBase();

while(true)
{
task_ADC();
light();

}
return 0;
}

efbrgn
06.03.2008, 15:01
ok das Problem habe ich gelöst, allerdings sagt er jetzt das "task ADC" zwei Bedeutungen hat.

efbrgn
06.03.2008, 15:19
ich mache Fortschritte:):)
habe ihn der Anleitung gelesen,dass man es jetzt auch anders machen kann...


#include "RP6RobotBaseLib.h"


unsigned char brightOld=0;
unsigned char bright=0;

void light(void){
uint16_t LSR = readADC(ADC_LS_R);

if(LSR<=400){
bright = 1;
}
else if((LSR<1000)&&(adcLSR>400)){
bright = 0;
}
else if (LSR>=1000){
bright = 2;
}

if(bright != brightOld){
switch(bright){
case 0:
writeString_P("\nSchon bessa:)!!\n");
break;
case 1:
writeString_P("\nMach das Licht an!\n");
mSleep(100);
break;
case 2:
writeString_P("\nMir ist es hier zu hell!\n");
mSleep(100);
break;

}
brightOld=bright;

}

}



void main (void)
{

initRobotBase();

while(true)
{
light();
}
return 0;
}

aber auch da taucht ein Problem auf:
und zwar wenn ich den Finger davorhalte, sagt er mir ist es zu dunkel.
Aber wenn ich ihn wieder wegnehme sagt nichts.Eigentlich müsste er sagen schon bessa.
Und wenn ich den Finger wieder vorhalte sagt er nicht.
Ich muss erst wieder ne Lampe vorhalten und dann funktioniert das wieder mit dem Mir ist es zu dunkel.

zerush
06.03.2008, 15:27
Hier ist der Fehler:

else if((LSR<1000)&&(adcLSR>400)){

aus adcLSR musst du auch hier LSR machen ;)

efbrgn
06.03.2008, 15:32
jaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaa
=P~ =P~ =P~ =P~ =P~ =P~ =P~ =P~ =P~ =P~ =P~ =P~



MEIN ERSTES PROGRAMM IST FERTIG:


Danke für die Hilfe...hatte mir das zwar etwas leichter vorgestellt aber was soll:)...
jetzt wird erstmal stundenlang licht an und aus gemacht und mein Robo sagt mir bescheid:):)

efbrgn
06.03.2008, 15:38
Hier nochmal für alle,die auch Spaß am Licht aus und an machen haben wollen , das fertige Prog.



#include "RP6RobotBaseLib.h"


unsigned char brightOld=0;
unsigned char bright=0;

void light(void){
uint16_t LSR = readADC(ADC_LS_R);

if((LSR<1000)&&(LSR>400)){
bright = 0;
}
else if(LSR<=400){
bright = 1;
}
else if (LSR>=1000){
bright = 2;
}

if(bright != brightOld){
switch(bright){
case 0:
writeString_P("\nSchon bessa:)!!\n");
break;
case 1:
writeString_P("\nMach das Licht an!\n");
mSleep(1000);
break;
case 2:
writeString_P("\nMir ist es hier zu hell!\n");
mSleep(1000);
break;

}
brightOld=bright;

}

}



void main (void)
{

initRobotBase();

while(true)
{
light();
}
return 0;
}

radbruch
06.03.2008, 15:45
Hallo

Ich wollte euch eigentlich nicht zusätzlich verwirren. Der Code ist auch nicht von mir, er stammt aus der Library (RP6RobotBaseLib.c) und sollte nur zeigen, wie dort der Wert für adcLSR bei jedem 6. Aufruf aktuallisiert wird. Als Teil der Library wird der Code auch autmatisch mit dem Programm kompiliert, deshalb gibt es eine Fehlermeldung, wenn ihr die Funktion mit dem selben Namen zusätzlich noch in das Programm schreibt. Das war natürlich etwas fies es ohne Quelle anzuführen...

Das Task-System ist ja recht pfiffig, aber hat eben auch seine Fallen. Wenn man ein Programm mit nur einer Funktion schreibt, kann man auch darauf verzichten und die Helligkeitswerte mit readADC() direkt einlesen. Aber das habt ihr ja inzwischen selbst gekundet. Glückwunsch.

Gruß

mic

efbrgn
06.03.2008, 16:33
zugegeben, dass hat mich wirklich verwirrt allerdings war ich am Enden auch selber darauf gekommen, dass du dies nur aus der Library gezogen hast:)..