Und hats schon jemand ausprobiert?
Wenn ja funktionierts bei Euch?
Grüße,
Harri
So, Ziel ist erreicht. Ein Primitivst Regler hält Asuro die paar cm lang einigermaßen in Richtung. Weiters habe ich es jetzt so gemacht dass Asuro nur noch 10cm lang versucht einen Barcode zu finden. Wenn er bis dorthin keinen gefunden hat, bricht er ab.
Hier der aktualisierte Code:
Beispiel Anwendung der Funktion:Code:/*Einstellungen um Asuro fit für die Barcode-Funktion zu machen.*/ /*Geschwindigkeit links/rechts definieren=>damit Asuro geradeausfährt*/ #define BC_SPEED 90 /*Hell/Dunkel Schwelle für Odometrie. Linke Odometrie wird als Referenz verwendet*/ #define BC_OLSCHWELLE 600 #define BC_ORSCHWELLE 730 /*Hell/Dunkel Schwelle für Barcode*/ #define BC_LSCHWELLE 45 /*Einstellungen um das Barcode zu ändern.*/ /*ACHTUNG: Bei Veränderungen von BC_STRICH_ANZAHL müssen in der Funktion 2 Anpassungen vorgenommen werden! Näheres siehe in der Funktion!*/ /*Anzahl der Datenbits*/ #define BC_DATENBITS_ANZAHL 3 /*Anzahl der Striche(Startbit+Datenbits+Prüfbit inklusive Stoppbit)*/ #define BC_STRICH_ANZAHL 5 /*Wie oft pro Strich der Helligkeitswert gemessen werden soll ACHTUNG: dafür muss die Strichbreite angepasst werden*/ #define BC_ABTASTUNGEN_PRO_STRICH 5 /*Um im bin_erg[] eine 1 auszulösen, müssen pro Strich mindestens BC_ABTASTUNGEN_PRO_STRICH-2 Messwerte 1 sein. */ #define BC_LOGIKSCHWELLE 3 /*Anzahl der Werte im daten[] Array*/ #define BC_MAX_WERTE 55 /*Fehlercodes*/ #define BC_FEHLER_PARITY 255 #define BC_FEHLER_RICHTUNG 254 unsigned char fkt_barcode_lesen(void) { unsigned int ldata[2]={0},odata[2]={0}; unsigned int led_on[2]={0},led_off[2]={0}; unsigned int links=0,rechts=0,ges=0; unsigned char flag_l=0,flag_r=0,n=0,startbit=0,summe=0,index=0,dez_erg=0,richtung=0; unsigned char odo_counter=0,counter_l=0,counter_r=0,speed_l=BC_SPEED,speed_r=BC_SPEED; unsigned char daten[BC_MAX_WERTE]={0},bin_erg[BC_STRICH_ANZAHL-1]={0}; MotorDir(FWD,FWD); MotorSpeed(BC_SPEED,BC_SPEED); StatusLED(OFF); /*Wegstrecke(odocounter) ab Startbit messen*/ while(odo_counter<BC_MAX_WERTE) { OdometrieData(odata); MotorSpeed(speed_l,speed_r); /*Bei jedem Tick daten[] Array auffüllen.*/ if( (flag_l==0 && odata[0]>BC_OLSCHWELLE) || (flag_l==1 && odata[0]<BC_OLSCHWELLE) ) { counter_l++; FrontLED(ON); LineData(ldata); led_on[0]=ldata[0]; led_on[1]=ldata[1]; FrontLED(OFF); LineData(ldata); led_off[0]=ldata[0]; led_off[1]=ldata[1]; links=led_on[0]-led_off[0]; rechts=led_on[1]-led_off[1]; ges=(links+rechts)/2; if(ges<BC_LSCHWELLE) { daten[odo_counter]=1; if(startbit==0) { StatusLED(GREEN); startbit=1; } } if(flag_l==0) flag_l=1; else flag_l=0; if(startbit!=0) { odo_counter++; } } if( (flag_r==0 && odata[1]>BC_ORSCHWELLE) || (flag_r==1 && odata[1]<BC_ORSCHWELLE) ) { counter_r++; if(flag_r==0) flag_r=1; else flag_r=0; } if(Gettime()%75==0 && (counter_l>3 || counter_r>3) ) { if(counter_l<counter_r) { speed_l=speed_l+1; } else if(counter_l>counter_r) { speed_l=speed_l-1; } if( (counter_l>35 || counter_r>35) && startbit==0) break; } } MotorDir(BREAK,BREAK); MotorSpeed(0,0); /*Binärzahl aufbauen + Prüfbit*/ for(n=0;n<BC_MAX_WERTE;n++) { summe=summe+daten[n]; /*Wenn BC_STRICH_ANZAHL verändert wird, muss hier ein entsprechender Eintrag erfolgen*/ if((n+1)%BC_ABTASTUNGEN_PRO_STRICH==0) { if((n+1)==(BC_ABTASTUNGEN_PRO_STRICH*3) || (n+1)==(BC_ABTASTUNGEN_PRO_STRICH*5) || (n+1)==(BC_ABTASTUNGEN_PRO_STRICH*7) || (n+1)==(BC_ABTASTUNGEN_PRO_STRICH*9)) { if(summe>=BC_LOGIKSCHWELLE) bin_erg[index]=1; else bin_erg[index]=0; index++; } summe=0; } } /*Richtung erkennen*/ /*Wenn BC_STRICH_ANZAHL verändert wird, muss hier der Faktor angepasst werden.*/ summe=0; for(n=(BC_ABTASTUNGEN_PRO_STRICH*9);n<(BC_ABTASTUNGEN_PRO_STRICH*11);n++) { summe=summe+daten[n]; } if(summe>=(BC_ABTASTUNGEN_PRO_STRICH*2-BC_LOGIKSCHWELLE)) richtung=1; /*Binärzahl umwandeln in Dezimalzahl oder Fehlercode zurückgeben*/ /*alles OK => Dezimalzahl zurückgeben*/ if((bin_erg[0]+bin_erg[1]+bin_erg[2])%2!=bin_erg[3] && richtung==1) dez_erg=4*bin_erg[0]+2*bin_erg[1]+1*bin_erg[2]; /*Fehlercode BC_FEHLER_RICHTUNG->falsche Richtung*/ else if((bin_erg[0]+bin_erg[1]+bin_erg[2])%2!=bin_erg[3] && richtung==0) dez_erg=BC_FEHLER_RICHTUNG; /*Prüfbit falsch*/ else dez_erg=BC_FEHLER_PARITY; StatusLED(OFF); return dez_erg; }
Code:unsigned char fkt_taster(void); int main(void) { unsigned char c=0,d=0; Init(); while(1) { c=fkt_barcode_lesen(); SerPrint("\r\nBarcode="); PrintInt(c); if(c!=255 && c!=254) { for(d=0;d<c;d++) { Msleep(500); StatusLED(GREEN); Msleep(500); StatusLED(OFF); } } while(fkt_taster()==0); } return 0; } unsigned char fkt_taster(void) { unsigned char taster=0; taster=PollSwitch(); if(taster==PollSwitch() && taster!=0) return taster; else return 0; }
Grüße,
Harri
Und hats schon jemand ausprobiert?
Wenn ja funktionierts bei Euch?
Grüße,
Harri
Grüße,
Harri
Ja, gerade eben ausprobiert.
Ich musste erst noch eine andere Breite für die Barcode-Striche und -Lücken in EXCEL suchen, und so kann ich erst einmal alle Barcodes zu ca. 80% lesen, die GENAU EIN schwarzes Datenbit haben.
2 schwarze Datenbits werden eher nur zu 10% gelesen, und alls 3 Bits in schwarz habe ich bis jetzt noch nicht geschafft.
Versucht habe ich es mit 5 verschiedenen Breiten der Striche. Der erste Druckversuch mit der rein mathematisch berechneten Breite (8-er ODO => 1.5 mm/Tik) hatte eigendlich auch noch am besten funktioniert.
Alle nicht gelesenen Codes liefern nach einem 'Zufallssystem' die beiden Fehlermeldungen zurück. (Richtung, Prüfbit)
Trotzdem schon mal nicht schlecht Herr Specht.
P.S.: Liegt es am Stopcode-Bit?
Ich habe es wie im oberen Bild gedruckt, da es so aus der EXCEL-Tabelle herraus druckbar ist im Gegensatz zu dem Image, welches du da abgelegt hast. Das Image deutet aber eher ein Stop-Bit an, welches direkt ohne Lücke hinter dem Prüfbit zu malen wäre bei doppelter Breite. (Vielleicht hast du es ja schon beschrieben, aber im Moment finde ich dazu keine Angabe.)
Lieber Asuro programieren als arbeiten gehen.
Wenn du eine 8er ODO hast musst du BC_ABTASTUNGEN_PRO_STRICH von 5 auf 10 setzen. Weiters würde ich mit der BC_LOGIKSCHWELLE etwas raufgehen, so ein Wert um 7 sollte passen.
Asuro muss über eine weiße Fläche fahren, sobald er den ersten schwarzen Strich erkennt fährt er genau 165mm weit. Das kannst du ja ausmessen und damit vergleichen ob du die Werte richtig eingestellt hast.
Weiters solltest du darauf achten dass die Barcodes möglichst millimetergenau gedruckt werden.
Das Stoppbit(in der Breite von 2 Strich) verschmilzt mit dem eventuell vorhandenen Prüfbit(als ein max. 45mm breiter Strich kann entstehen im Extremfall).
Ich hab mal die Zahlen 4...7 im Anhang angehängt, da sollte man es schön erkennen.
Wenn du außerdem AutoCAD hast kannst du dir die Barcodes von dort ausdrucken(siehe Anhang), du musst nur das Rechteck um die Barcodes an die druckbare A4 Größe anpassen, und dann beim Plotten dies als "Fenster" wählen. Damit kann man dann auf den mm genau drucken.
Ich hoffe dass es nun bei dir funktioniert, sonst helf ich natürlich gern weiter(mich interessiert es ja schließlich auch wie "portabel" so ein Asuro Programm denn ist).
Dieses WE werde ich mal etwas angehen was mich schon seit Ewigkeiten nervt: Eine vernünftige Geradeausfahr-Regelung für Asuro. Ich hab zwar schon einen PI Regler mal gebaut aber diesmal probier ich es auf einen anderen Weg womit man hoffentlich noch bessere Resulate erzielt. Damit man Asuro auch mal perfekt gerade über Strichcodes fahren lassen kann.
Grüße,
Harri
Grüße,
Harri
Hallo harry3,
den PID-Regler von waste, unter diesem Link kann ich nur empfehlen. waste hat ihn zwar für die Linienverfolgung geschrieben, aber ein kleiner Umbau, und schon kann er auch geradeausfahren.
Ich habe eine Interrupt-Feste Version davon, soll heißen man kann geradeausfahren 'lassen' und sich dann um seine eigentliche Aufgabe (Barcodes?) kümmern. Interresse?
Lieber Asuro programieren als arbeiten gehen.
Ja zeig mal her den Code für die Interrupt Funktion.
Ich hab den Regler etwas anders in Planung, aber schaden kann es ja trotzdem nicht andere Ideen zu sehen.
Grüße,
Harri
Grüße,
Harri
Hier kommt dann mal die Ersatz-Asuro-LIB von SternThaler.
Kleine Übersicht:
--- Timer-Interrupt:
Sorgt mit dem langen, aber schnellen Code für das 'anschieben' eines weiteren ADC-Wandlers.
--- main()-Funktion:
- Starten der gewünschte Wandlergruppe (Hier sinnvoll: ODO)
- Fahrstrecke vorgeben
- Loop-Schleife mit zeitgesteuertem Sheduler
- Alle 2ms den PID-Regler von waste aufrufen
--- waste-PID-Regler:
Je nach gewünschtem Regelverhalten ODO- oder LINIEN-Regler nutzen.
Timer-Interrupt und waste-PID-Regler sind in asuro_st.c/h
main() natürlich in test.c
Hinweise:
- Tik-Anzahl-Vorgabe bei den Tasten bezieht sich auf 8-er Scheiben.
- Infos zur Tastenbelegung in test.c. (Asuro von vorne ansehen: Taste 1 = links)
- ODO-Messungen benötigen Anpassungen für die Tik-Ermittlung.
In der Datei asuro_hw.h sind dafür die Defines HW_RAD_SCHWELLE_LINKS und HW_RAD_SCHWELLE_RECHTS
@harry3
Ich möchte nicht, dass du aus meinem Code die Kommentare entfernst, die Funktionsnamen änderst und dann in deinem Link "Meine erstellten Asuro Funktionen..." wieder auftauchen [-X .
Lieber Asuro programieren als arbeiten gehen.
Danke ich werds mir anschauen.
Hab aber inzwischen bereits eine gute Lösung hinbekommen mit Hilfe eines einfachen P Reglers(der I Anteil steckt eh schon in der gemessenen Wegstrecke drinnen).
Wenn ich Codeteile von anderen verwendet habe habe ich diese immer namentlich erwähnt(und das ist im konkreten Fall nur der PID Linienfolger von waste). Die von mir ins Internet gestellte Headerdatei wird jetzt aber sowieso verschwinden weil ich meine ganzen Funktionen nun in eine Menge Einzeldateien geteilt habe um Speicherplatz zu sparen und um etwas mehr Übersicht in die Sache zu bringen.Zitat von Sternthaler
Hier nun der aktuelle Code zum Barcodelesen mitsamt des Reglers:
hs_barcode.h
Grüße,
Harri
Hallo harry3,
ich habe gerade in deine hs_barcode.h geschaut. (Warum eigendlich immer *.h?)
Ist auch eine schöne Lösung für die 'parallel' zu erledigenden Arbeiten. Da wirst du dich bestimmt wundern, wie kompliziert ich es gemacht habe.
Im Kommentar deiner Datei schreibst du folgendes:Kann es sein, dass du die 6-er Scheiben meinst?WICHTIG: Die Funktion wurde für die 8er Odometriescheibe ausgelegt(1 Tick=3mm).
Bei meinen 8-er-Scheiben fahre ich nämlich 1,5 mm / Tik.
Aber warum sollte man dann bei einer 6-er-Scheibe auf 3 mm / Tik kommen?
Das Verhältnis 8 zu 6 entspricht ja nicht 3 zu 1,5. Gibt es beim Asuro eventuell noch andere Getriebeuntersetzungen / Raddurchmesser?
Meine beiden Zahnräder haben laut Anleitung jeweils eine Untersetzung von 50 zu 10. Der Raddurchmesser beträgt ca. 38.1 mm
Rad-Umfang also 119,7 mm
Umfang / eine Getriebestufe = 119,7 / 5 = 23,94 mm
Das durch 8 * 2 SW- bzw. WS-Wechsel = 23,94 / 16 = 1,496 also ca. 1,5 mm / Tik. (bei meinem Asuro)
P.S.: Mit der Anleitung, dass das Stop-Bit eine doppelte Breite hat, ist die Trefferquote bei mir auch eine 'Ecke' besser geworden.
Lieber Asuro programieren als arbeiten gehen.
wenn man es genau betrachtet, hat die andere scheibe auch nicht 6 flächen, sondern 12 8schwarz und weiss).
raddurchmesser: ~38 mm
umfang: ~120 mm
nach getriebestufe: ~24 mm
durch ticks: ~2 mm.
gute frage woher dann die 3 mm kommen... wer hat das nur ausgerechnet...
Lesezeichen