Go Down

Topic: AUDIOINO, eine minimalistischer Arduino mit Programmierung über Line Out (Read 11217 times) previous topic - next topic

25mmHg

Hallo Chris, ich habe mir heute ein PingPongBoard genommen und mit einem AVRISPmkII ist es mir gelungen, den Bootloader zu flashen. Es gab eine Hürde: Die vielen LEDs! Am Anfang unerklärliche Übertragungsfehler und Abbrüche. Nach verzweifeltem Hin- und Herschalten des ISP-Clocks leuchteten auf einmal Streifenweise LEDs auf!!! So bin ich drauf gekommen, das Board nicht alleine mit dem AVRISPmkII zu  betreiben, sondern mit einem Labornetzteil 5V. Ohne die LEDs wäre es sicher auch ohne zusätzliche Spannungsquelle gegangen, aber in diesem Falle ist unbedingt eine autonome Versorgung des Boards nötig.

Das PingPongBoard hat nach  http://www.produktinfo.conrad.com/datenblaetter/900000-924999/902766-an-01-ml-CONRAD_RETRO_SPIEL_PING_PONG_de_en_fr_nl.pdf die folgenden PortPins frei nach draußen gelegt:
PC4 und PC5 (ATmega8) als C4, C5 (PingPong) und PD0 bis PD3 (Atmega8) als D0, D1, D2, D3 (PingPong)
Außerdem sind ADC6 und ADC7 für die Verwertung analoger Signale als P2 und P3 rausgeführt.
All diese PortPins sind völlig unbeschaltet und damit meiner Meinung nach wahlfrei verwendbar. K1 steht noch als GND und P1 als VCC zur Verfügung.

Ich habe mir überlegt, PC4 und PC5 für LEDs zu nutzen (Status und Test) und D0(RXD) als AUDIOIN zum Flashen. Spricht da irgendwas dagegen? Den Code kann ich sicher umschreiben. Das such ich mir zusammen. Aber eine Sache hat mich noch stutzig gemacht. Muß ich dem Bootloader noch irgendwo mitteilen, wie groß der FlashRom des Atmega8 ist?
Ganz unten in Deinem Code stehen folgende Zeilen (Vom pageweisen Speicheraufbau und vom Verhältnis FlashRom 4kwords (ATmega8) zu 8kwords (ATmega168) weiß ich):

case PROGCOMMAND:
       {
           // Atmega168 Pagesize=64 Worte=128 Byte
         uint16_t k;
         k=(((uint16_t)FrameData[PAGEINDEXHIGH])<<8 )+FrameData[PAGEINDEXLOW];
         boot_program_page (SPM_PAGESIZE*k, FrameData+DATAPAGESTART);   // erase and programm page
        }
       break;

Viele Grüße Johannes

mmi


Ohne die LEDs wäre es sicher auch ohne zusätzliche Spannungsquelle gegangen, aber in diesem Falle ist unbedingt eine autonome Versorgung des Boards nötig.

Die autonome Versorgung des Boards bzw. Prozessors ist bei Verwendung des AVRISP MKII grundsätzlich notwendig. Der AVRISP misst lediglich die von Dir angelegte Spannung, um sich z.B. auf einen 5V oder 3,3V Prozessortyp einstellen zu können. Wie sollte er es sonst auch automatisch erfahren können.

Gruß, mmi

25mmHg

Danke mmi, ich habe einen AVRISP-Clon (cc2AVRprog), und der hatte zumindest die Möglichkeit das VCC-Pin zu versorgen. (sonst hätten nicht 40 LEDs aufgeflackert) aber gereicht hat das eben trotzdem nicht, wahrscheinlich reichte der Speisestrom nicht und es gab Betriebsspannungseinbrüche.
Mit Netzteil klappt das Flashen sicher. Ich hab mir eine Adapterplatine auf einen D-SUB15Stecker gebaut. Mit den verfügbaren Leitungen drauf. So kann ich irgendwelche BE gleich auf eine SUB-D15Buchse löten und rumexperimentieren. Einen Resetschalter braucht man beim PingPongBoard nicht, da GND und RESET sich auf dem ISP-Steckverbinder (den man hier selber bestücken muss) gegenüber befinden, so dass ein einfacher Jumper ausreicht.
Hier noch ein Link für alle die einen echten AVRISPmkII haben und ihr Target trotzdem speisen wollen: http://www.youtube.com/watch?v=ICQXqVy3Hpc
Viele Grüße Johannes


25mmHg

Hallo Chris, jetzt gibt es in Bezug auf Audiobootloader und PingPongBoard folgenden Stand. Der Bootloader lässt sich auf den ATmega8 überspielen, die geänderten Pinbelegungen sind mit eingeflossen. Nach einem RESET blinkt die StatusLED langsam, und auf dem AudioINPUT werden Daten von der Soundkarte empfangen. Allerdings scheint trotzdem etwas nicht zu klappen:

1.) Das Blinken geht ewig, und hört nie nach 6s auf (vielleicht weil kein Code im Flash vorhanden ist, der angesprungen werden kann?)
update: Ich habe gerade mein Testprogramm mit dem AVRISPmkII geflasht und danach ohne Chip-erase den Audiobootloader drauf. Jetzt wird nach 6s pünktlich zum Testprogramm gesprungen
2.) Ich schaffe es, Programmierfehler auszulösen, die durch schnelles Blinken der StatusLED angezeigt werden, wenn ich den Audiopegel voll aufdrehe
3.) Wenn ich den Pegel des Audioausgangs vom Laptop etwas zurückdrehe finde ich einen Bereich, in dem die StatusLED zu einem Dauerleuchten übergeht, aber zur Ausführung meines Testprogramms gelange ich nicht.

Ich habe auch mal einen 10nF Kondensator in der Audioleitung versucht, ohne Verbesserung.
Jetzt will ich erstmal das RESET-Pin mit einem externen Pull-UP versehen
Gruß Johannes

Hallo Johannes,

100nF für den Wert des Koppelkondensators sind besser.

Ich vermute, dass das Problem wo anders liegt: Der Atmega8 hat eine Pagesize von 64 Byte und der Atmega168 hat eine Pagesize von 128 Byte.
Beim Audiobootloader werden immer 128 Byte an Daten übertragen und dann dem Mikrocontroller etwas Zeit gegeben, eine Page zu "flashen".
Eine Umgehungslösung für den Atmega8 könnte sein, auch 128 Bytes zu empfangen und dann einfach 2 aufeinander folgende 64 Byte Pages zu flashen.
Sonst müsste man auch das Java Programm ändern und dort die Datengröße auf 64 Byte umstellen und den Bootloader für den Atemga8 ändern, was etwas aufwändig wäre.

Bester Gruß,
chris

25mmHg

Hallo Chris, einmal könnt ich es ja mal machen...Ich fange also an, das Audio-file zu zerschneiden...Hoffentlich habe ich ein kurzes Testprogramm.
(Schneiden kann ich ja - Aber den Bootloader umstricken sicher nicht)
Aber dann wird es jetzt richtig spannend.
Viele Grüße Johannes

Quote
Hallo Chris, einmal könnt ich es ja mal machen...Ich fange also an, das Audio-file zu zerschneiden...Hoffentlich habe ich ein kurzes Testprogramm.


Schneiden? Ich glaube, das dürfte nichts bringen. Ausser Dein Programm ist 64 Byte lang.


Du könntest für die Pages verantwortliche Stelle im Programm modifizieren. Das hier schreibe ich jetzt einfach mal hin, ohne es getestet zu haben:

relativ weit oben im Programm
// fuer Atmega8
#define PAGESIZE 64 // Pagesize for Atmega8
#define FRAMESIZE       (PAGESIZE*2+DATAPAGESTART)// framsize still 128 byte


Weiter unten:

case PROGCOMMAND:
        {
            // Atmega168 Pagesize=64 Worte=128 Byte
            // Atmega8 Pagesize=32 Worte=64 Byte

         uint16_t k;
         k=(((uint16_t)FrameData[PAGEINDEXHIGH])<<8 )+FrameData[PAGEINDEXLOW];
         boot_program_page (SPM_PAGESIZE*k*2, FrameData+DATAPAGESTART);   // erste 64 byte des Datenframes
         boot_program_page (SPM_PAGESIZE*k*2+1, FrameData+SPM_PAGESIZE+DATAPAGESTART);   // zweite 64 Byte des Datenframes

         }
        break;



25mmHg

Danke Chris für diesen Vorschlag. Erfolg hatte ich noch nicht. (Irgendwas scheint noch nicht aufzugehen) Bin gerade dabei, mich durch den Audiobootloader und die boot.h zu wühlen. Eine mail an elo bzw. B. Kainka hab ich geschrieben, weil die ja das PingPongBoard entwickelt haben. Auch dort stieß der Audiobootloader auf großes Interesse. Wenns was neues gibt, melde ich mich wieder. (6Schreibmaschinenseiten++ zu verstehen dauert sicher eine Weile...und Zeit hab ich nur spät abends)
Viele Grüße Johannes

Hallo Johannes,

jetzt habe ich doch ein wenig Zeit investiert und den Audiobootloader für das PingPong Game zum laufen gebracht:
http://www.hobby-roboter.de/forum/viewtopic.php?f=4&t=127&p=542#p542
Als Eingang habe PD1 verwendet. Die Widerstände muss man bei meinem Ping Pong Game auf 1.4V Mittelspannung bei 5V Versorgung anpassen. Eventuell wäre es hier am besten ein Poti zu verwenden.

Da die Sourcen im Moment noch etwas Spaghetti Code sind, habe ich erst mal nur die HEX-Files gepostet.

Bester Gruß,
chris

Gerade eben habe ich noch einen Fehler gefunden: bei manchen Rechnern ist das Audiosignal invertiert. Da scheint es wohl keine eindeutige Norm zu geben oder die Hersteller halten sich nicht daran. Im Moment funktioniert der Audiobootloader nur mit einer Polarität.
Ich überlege noch, wie ich das Problem lösen könnte:

1. Java Programm mit Polaritätsknopf versehen ( unschön, weil man dann den Knopf richtig betätigen muss )
2. MC-Programm auf automatische Polaritätserkennung anpassen ( ziemlich aufwendig )

Im Anhang noch ein kleines Demoprogramm für's Ping Pong.


25mmHg

Hallo Chris, vielen Dank für Deine Forschungsarbeit. Ich hätte noch eine Idee, wie man die Sache mit der falsch gepolten Soundkarte lösen kann: eine etwas andere Codierung. Fündig bin ich beim differentiellen Manchester Code geworden. http://www.staff.hs-mittweida.de/~win/vorlesungen/Grundlagen_KT_4.pdf Hier ist auf Seite 21 etwas mehr über das Prinzip zu erfahren. Dieser Code ist ebenfalls über Koppelkondensatoren und Übertrager transportierbar und nutzt Flanken egal welcher Richtung zur Codierung der NULL beim Taktwechsel. Bei der Codierung der EINS wird zum Taktwechsel einfach der Pegel beibehalten. In der Taktmitte wechselt der Signalpegel immer, damit aus dem Signal der Takt rückgewonnen werden kann. Somit ist dieser Code resistent gegen Vertauschung der Signaladern eines Kabels.
Soweit erstmal die Idee von mir.
Ich probier das mit der anderen Phase aber erstmal mit dem PingPongBoard aus.
Was musstest Du sonst noch im Code anpassen?


Viele Grüße Johannes

Hallo Johannes,

das mit dem differentiellen Manchestercode ist auf jeden Fall eine sehr gute Idee, das Problem zu lösen. Allerdings würde der Umbau einiges an Arbeit erfordern.
Für die invertierten Signale habe ich einfach das Java-Programm neu compiliert. Ich musste nur ein Flag umstellen, da das Programm ohnehin schon für invertierte Signal vorbereitet ist. Jetzt gibt es zwei Programme, eines für invertierende und ein anderes für nicht invertierende Soundkarten.
Damit das Ganze für den Atmega8 funktioniert, musste ich auch die Pause zwischen den einzelnen Frames von 10ms auf 20ms umstellen, da die Flash-Routine im Bootloader für den Atmega8 zweimal pro Frame aufgerufen wird und damit doppelt so viel Zeit braucht.
Als Anzeige für den Bootloadervorgang habe ich direkt die LEDs des Ping-Pong benutzt. Dort wird während des Bootens auch der aktuelle Frame als Binärzahl angezeigt.

Läuft der Bootloader bei Dir?

Gruß,
Christoph

25mmHg

Hallo Chris, seh mir gerade Deinen Quellcode an. Hab eben erst entdeckt, dass Du ganz viel dran gemacht hast. Schön, dass der ATmega8 jetzt voll mit eingebunden ist. Und ganz großes (Mäuse)Kino. Morgen mach ich die Elektronik-AG, und da werd ich das nicht nur alleine bestaunen. Und ich hoffe ein paar PingPongBoardBesitzer lesen hier mit!!! Gut finde ich (wenn ichs richtig erkannt habe), dass Du auch an den Batterieverbrauch gedacht hast und den Spannungsteiler auf ein PortPin gelegt hast und somit stromlos schaltest, wenn er sein Werk getan hat.
SOMIT HABEN WIR JETZT EIN PINGPONGBOARD mit 120 LEDs(manche haben nur 5€ dafür bezahlt), WAS AN DER BATTERIE BLEIBEN KANN UND MIT EINEM KLEINEN KLINKENKABEL PROGRAMMIERBAR IST S-U-P-E-R-G-E-N-I-A-L

Johannes .-)=

Nachtrag: Ich sehe die Matrix!!! Ich habe mir den Quellcode von Dir nochmal neu compiliert, weil ich meinen Adapter nicht umbauen wollte. (Bei mir ist also PD0 AudioInput. Ich habe 10k+10k+100n als Anpassungsnetzwerk. Das Hochzählen vom Bootloader ist eine mittelgute Hilfe, wenn man den Audiopegel einstellen will. Ich habe jedenfalls nicht den vollen Pegel der Netbooksoundkarte benötigt. Was hältst Du eigentlich davon, wenn man beim PingPongBoard (Das hat genug) zur Audiopegelkontrolle zwei benachbarte LEDs mitlaufen lässt, eine für HIGH und eine für LOW. Man könnte die Umschaltschwelle sehen und wenn beide LEDs gleich hell leuchten müssten sich die Zeiten für LOW und HIGH gleichen. Und das wäre dann der optimal eingestellte Manchestercode (DC-neutral). Ich vermute aber, dass das einen Interrupt kostet, weil ja die Routine beim Frameempfang ganz schön hin und her hopst.

Und ich habe was gefunden (Hab also wirklich den Code durchgelesen): Der HIGHFuse Wert 0xD8 wird zumindest auch als 0xDA akzeptiert. Und 0xDA und müsste nach meiner Rechnung für 1Kbyte Bootloadergröße auch stimmen.
Außerdem müssen die Bits BOOTSz1u0 anders gesetzt werden bei 1Kbyte Bootloadergröße:
ATMEGA8 (1Kbyte bootloader) Fuses: BOOTSz1=0(x); BOOTSz0=1(o); Linker: -Wl,--section-start=.text=0x1c00

Fuses for PingPong, Atmega8:
HIGH:0xDA
LOW:0xE4
LOCK:0xCF

Also wieder die Verwirrung von Wort und Byte...
Und hier die Käferecke:
Habe bei Berechnung der FRAMESIZE was gefunden. (hebt sich aber beim Compilieren auf)
Und von Zeile 399 bis Zeile 423 und Zeile 424 bis Zeile 448 wiederholt sich exakt der gleiche Code einmal für ATmega168 und ATmega8.
Dort kann man bestimmt die Hälfte streichen und die #ifdefs wegnehmen.

Also Chris, ich bastel morgen noch ein bischen weiter ... einen RESET-Taster den ich auf den ISP-stecken kann und gehöre aber jetzt ins Bett.
Danke für die tolle Idee.
Bis bald.
Herzliche Grüße Johannes (nochmal editiert am 23.5.19:00)

(Seit heute nachmittag läut das Flashen sehr stabil und reproduzierbar. Frühere Fehlversuche gehen auf eine nicht straff sitzende Masseverbindung beim Audio-Cinchkabel zurück. Hier hätte also eine Pegelkontrolle per LED-vergleich Punkte gesammelt. Ich habs auf dem Oszilloskop gesehen. Mit straff sitzender MAsse keinen eintzigen Fehlversuch mehr! Meine Soundkarte benötigt jetzt nur ca. 50% Maximalpegel um sicher über die LOWHIGH-Hürde zu springen (knapp 3,5V Spitze-Spitze). Ich habe noch einen Anschluss fürs Oszilloskop und den Reset-Taster vorgesehen und freue mich immernoch, dass alles so gut funktioniert. Ein Poti hab ich erstmal nicht benötigt )

Hallo Johannes,

es freut mich seht, dass der Bootloader bei Dir jetzt stabil läuft.  XD
Bei mir läuft er auch sehr stabil und man benötigt tatsächlich kein Programmiergerät mehr. Nur das Original Ping-Pong läuft nicht, weil es wohl nicht in die verbleibenden 7KFlash passt.

Das mit dem Pegel hatte ich mir auch schon überlegt. Allerdings ist der Bootloader ja für einen Digitaleingang gemacht. Da kann man nur zwischen low- und high unterscheiden. Um den Pegel wirklich zu messen, müsste man einen ADC-Pin verwenden und zusätzlich einen ADC-Treiber einbauen.

Welche Spannung musstest Du als Mittenspannung einstellen? Welches Widerstandsverhältnis hast Du gewählt? Bei meinem Ping-Pong ist es wie weiter oben beschrieben bei 1.4V bei 5V Versorgung.

Programmieren Deine Schüler auch in C?

Bester Gruß,
chris

25mmHg

Hallo Chris, das ist es ja! ich habe orginal 10k+10k drin angekoppelt mit 100n und ich musste nichts nachstellen.
Was die AG betrifft: Sie ist eine sehr kleine AG, aber dafür sinds sehr zuverlässige Leute. (Im Kern sind wir zu dritt und 40+Jahre alt) Und seit ein paar Monaten dreht sich fast alles um C und um den Arduino, mit dem alles angefangen hat. Aber nun wollen wir halt näher an die Hardware ran. Wir haben heute die ganzen 12Seiten Quelltext ausgedruckt und auf den Tisch gelegt...
Also nun noch mal zu meiner Idee:
Auf dem Oszilloskop hab ich gut sehen können, was passiert, wenn RESET gedrückt wird. Am AudioPin fällt die Spannung auf den halben Wert und nach Start der Übertagung wird der Spannungsraum zwischen GND und VCC zu gut 75% mit der codierten NF ausgefüllt. Ich habe übrigens immer auf dem zweiten Audiokanal einen kleinen Kontrollautsprecher(aktiv) mitlaufen.
Wenn der Audiopegel in pos. Richtung VCC übersteigt entstehen Verzerrungen und die Übertragung wird fehlerhaft. Irgendwann müssen doch auch die internen ESD-Schutzdioden anfangen zu leiten (so es welche gibt) . Vielleicht bringt ja auch ein Serienwiderstand ca. 0,5-1Kohm noch eine Verbesserrung. Aber nun endlich die Idee:
Ich stelle mir ein "etwas" vor, das den Tatsächlichen Wert des PIND1 Registers (bei mir PIND0) auf zwei LEDs mappt. und zwar so: LED1= PIND0; LED2= ~(PIND0); So kann man sehen welchen Wert PIND0 gerade hat und kann vor allem beurteilen, ob PIND0 genauso oft HIGH ist wie LOW. Wenn also der BIAS zu tief eingestellt ist, wird LED2 dauernd oder heller leuchten. Wenn er zu hoch eingestellt ist, leuchtet LED1 dauernd oder heller. Wenn eine Übertragung stattfindet und beide LEDs leuchten gleich hell, dann zeigt das an, das der BIAS ungefähr in der optimalen Mitte liegt. Man müsste zur Feinabstimmung mit dem Potischleifer hin und herpendeln und dann den Mittelwert der beiden Extrempunkte abschätzen (Lineares Poti Voraussetzung) Das geht aber nur mit zwei LEDs, da man mit einer LED zwar den momentanen Wert von PIND0 sehen könnte, aber eben nicht vergleichen kann, ob sie genausolange an wie aus ist. Zumindest eben sollte man mit den LEDs die Umschaltpunkte der Eingangslogik besser auffinden können. Beim Übertragen von Code sieht man dann auch, ob der AudioPegel ausreicht, den Digitaleingang zum Kippen zu bringen. Also benötigen wir keinen ADU
Weißt Du wie ich das meine?
Ich hab halt Vorstellungen im Kopf aber bin meilenweit davon entfernt, daraus C-Code zu formulieren.  Ich denke nur, dass vielleicht ein PIN-change Interrupt weiterhelfen könnte, aber damit schränkt man die zur Verfügung stehenden PINs gewaltig ein. Die andere Lösung wäre an jeder Flankenabfrage den Anzeige-Code dranzuhängen oder eine Flankenabfragefunktion zu bauen, die beim Frameempfang an allen Abfragepunkten immer wieder aufgerufen wird und die die LED-Ansteuerung zusätzlich mit übernimmt. Und dann kann man sich ja für zwei benachbarte LEDs auf dem PingPongBoard entscheiden. Das mit dem Fortschrittsbalken beim Frameempfang wie jetzt schon eingebaut find ich schon Spitze.

Viele Grüße Johannes

Go Up