Hallo Freunde der Elektronik. Ich habe folgendes Problem. Für ein Projekt an dem ich arbeite, muss ich unter anderem einen uC so implementieren, dass er beim Eingang von Daten den PWM Pin auf High setzt(welcher für eine NPNTransistor Schaltung von Nöten ist). Für dieses Vorhaben habe ich den Attiny25 ausgewählt welcher für mich genügend Flash zur Verfügung stellt. Jetzt will ich hier aber keine TWI Kommunikation(USI), da es das ganze unnötig verkompliziert, sondern den Attiny mit Hilfe eines Arduinos und dem Software Serial Befehl programmieren. Leider ist es das erstemal, dass ich mich mit dem Thema Kommunikation befasse, deshalb hab ich nicht wirklich einen Plan von dem Vorgang. Hat jemand eine Idee, wie ich hier vorgehen sollte? Ein Tutorial für das flashen von Attinys mit dem Arduiono habe ich schon gefunden. Datenblatt: http://www.atmel.com/images/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf Danke für die Hilfe im Voraus. Faisal
:
Verschoben durch Moderator
Es wäre auf jeden Fall hilfreich, wenn du dein Vorhaben noch etwas genauer beschreibst. 100%'ig sicher was du vor hast bin ich mir nämlich nicht. Ich nehme mal an du hast einen Standard Arduino Uno (mit Atmega328/168 oder 8) der dem ATTiny irgendwelche Befehle schicken soll. Dann kannst du wunderbar den UART vom Arduino zum Senden nutzen. Allerdings musst du die Daten auch auf deinem ATTiny entgegen nehmen. Im Moment gibt es nur den ATTiny 167/87 der einen Hardware Lin/UART hat. Somit müsstes du auf Soft-UART zurück greifen. Da solltest du hier im Forum genug zu finden AVR304/305 sind immer so ein Stichwort. Ich nutze dann meist eine einfache Version der AVR305 Application Note, welche in inline assembler gepackt wurde. Ist mit senden/empfangen etwa 100 Byte groß. https://github.com/Whistle/avr305 Die eigentlichen Routinen sind in der avr305.h
:
Wiederhergestellt durch User
@Johann Danke erstmal für die Antwort. Das Vorhaben sollte wie folgt sein: Es sollen keine Befehle über dem Arduino geschickt werden, sonder lediglich programmiert werden. Ja es ist ein Arduino mit dem Atmega 328. Die Daten werden über eine Software an das Board geschickt(RS232 Protokoll-Standard) dementsprechend habe ich ein Max3221 davor geschaltet. Jetzt soll der der Attiny die Daten einfach nur lesen bzw. empfangen und daraufhin einen PWN pin auf High schalten. An diesem PWN Pin ist einen NPN Transistor geschaltet. Dieser sollte nun seine übliche Funktion(durch den HIGh Pegel am PWN) ausüben. Ungefähr jetzt auf einer Höhe? :-) Danke nochmal
Ahh okay, jetzt weiß ich bescheid. Der Arduino wird als ISP genutzt. Den Quelltext kannst du trotzdem nutzen, auch wenn ich dich nicht richtig verstanden hatte. Die Funktion readc() liest dir dann auf deinem Wunsch-Pin jeweils ein Zeichen ein. Welcher Pin genutzt wird setzt du mittels der defines in avr305.h. Die Baudrate kannst du dort auch setzen. Ist eigentlich selbsterklärend. Wenn noch Fragen aufkommen ruhig fragen. Ich helfe gerne. Mit freundlichen Grüßen Johann Schiller
@Johann Danke nochmal für die Antwort. Den Quelltext habe ich mir erst jetzt angeschaut. Das wichtige war bei mir, dass ich das USI Interface nicht nutzen wollte, da ich das Board schon erstellt habe und die Pins des Attinys´ schon für UART ausgelegt hatte... Deswegen fällt das TWI weg. AVR305 sieht gut aus. Vor allem, dass ich den Pin einstellen kann. Ich Versuch das gleich am Montag im E-lab aus und sag Bescheid ob es geklappt hat. Grüße Faisal Alam
So ich habe das nochmal getestet. Das ganze sieht jetzt gut aus, jedoch bräuchte ich weitere Hilfe. Wie liest man beim Softuart einen String ein? Muss da jeder einzelne Char abgetastet werden? Grüße Faisal
> Wie liest man beim Softuart einen String > ein? Muss da jeder einzelne Char abgetastet werden? Ja, natürlich. Der Soft-UART ist, genau wie ein Hardware-UART bei anderen Atmels Einzelzeichen-orientiert.
So Leute. Danke bisher für die Hilfe. Muss die ganze jetzt nochmal kurz aufwirbeln. Ich habe jetzt das Protokoll meiner Hardware vor mir liegen. VOn diesem Protokoll ist mir jetzt nur wichtig einen bestimmten string einzulesen. Ich hba mir dabei überlegt jeden char abzutasten, und daraufhin erst den rest des strings zu lesen. Hier ist der COde dafür:
1 | #define F_CPU 8000000UL
|
2 | |
3 | #include <util/delay.h> |
4 | |
5 | #include "avr305.h" |
6 | |
7 | #include <string.h> |
8 | |
9 | |
10 | |
11 | int main() { |
12 | |
13 | char c; |
14 | while(c=readc()){ |
15 | |
16 | |
17 | if(readc()='p') |
18 | |
19 | {char stringpwm[9],i=0,x; |
20 | |
21 | |
22 | while(x =readc()!=9) { |
23 | |
24 | stringpwm[i++]= x; |
25 | |
26 | }
|
27 | |
28 | stringpwm[i] = '\0'; |
29 | |
30 | |
31 | if (strcmp(stringpwm,"wrc0001")) |
32 | |
33 | {PORTB |= (1 << PB1); // PB1 auf high ; |
34 | |
35 | };
|
36 | |
37 | |
38 | |
39 | |
40 | else if (strcmp(stringpwm,"wrc0000")) |
41 | |
42 | {PORTB &= ~(1 << PB1); // PB1 auf Low |
43 | };
|
44 | |
45 | |
46 | else { |
47 | return;} |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | }
|
54 | else{ |
55 | return;} |
56 | |
57 | }}
|
Die Länge des Strings wurde so gewählt, da das Protokol am Ende eines Strings immer das Abbruch-Krit. <CR> hat. Am schnluss muss eigentlich nur der string pwrc0000 bzw pwrc0001 aus dem Protokoll herausgesucht werden. KLappt das so. Danke nochmal und grüße Faisal
:
Bearbeitet durch User
Hallo, hier mal ein paar Anmerkungen. Faisal Alam schrieb: > So Leute. Danke bisher für die Hilfe. Muss die ganze jetzt nochmal > kurz > aufwirbeln. > > Ich habe jetzt das Protokoll meiner Hardware vor mir liegen. > > VOn diesem Protokoll ist mir jetzt nur wichtig einen bestimmten string > einzulesen. > > Ich hba mir dabei überlegt jeden char abzutasten, und daraufhin erst den > rest des strings zu lesen. > > Hier ist der COde dafür: > > #define F_CPU 8000000UL > > #include <util/delay.h> > > #include "avr305.h" > > #include <string.h> > > int main() { > > char c; > while(c=readc()){ > > if(readc()='p') Das Zeichen wird in der while-Schleife bereits eingelesen, daher reicht ein Vergleich mit c. Außerdem musst du den Vergleich in C mit "==" machen. > > {char stringpwm[9],i=0,x; > > while(x =readc()!=9) { Warum findet hier ein Vergleich mit 9 statt? Du liest ein Zeichen, speicherst es in x und vergleichst es gegen 9 (mit Blick in die ASCII Tabelle wäre dies ein Tabulator. Ich glaube eher, das du nicht mehr als 9 Zeichen lesen möchtest. > > stringpwm[i++]= x; > > } > > stringpwm[i] = '\0'; > > if (strcmp(stringpwm,"wrc0001")) strcmp gibt eine 0 zurück wenn der Vergleich wahr ist. Daher muss noch ein ! vor das strcmp > > {PORTB |= (1 << PB1); // PB1 auf high ; > > }; > > else if (strcmp(stringpwm,"wrc0000")) > > {PORTB &= ~(1 << PB1); // PB1 auf Low > }; > > else { > return;} > > } > else{ > return;} > > }} > > Die Länge des Strings wurde so gewählt, da das Protokol am Ende eines > Strings immer das Abbruch-Krit. <CR> hat. > > Am schnluss muss eigentlich nur der string pwrc0000 bzw pwrc0001 aus dem > Protokoll herausgesucht werden. > > KLappt das so. > > Danke nochmal > und grüße Faisal Guck mal hier vielleicht: http://stackoverflow.com/questions/5697047/convert-serial-read-into-a-useable-string-using-arduino Kannst du ganz leicht adaptieren. MFG Johann
Erstmal Danke @Johann für deine Anmerkungen. Ich hab die so erstmal mit aufgenommen. Eigentlich müsste doch jetzt so das Programm jedes Zeichen erstmal abklappern nach einem 'p' . Falls dieser dann vorhanden ist, soll er die 7 Zeichen danach einlesen und diesen String erstmal vergleichen. Muss dafür der Platz für den String jetzt 7 sein oder 9(da am Ende jeder Zeile im Protokoll der carriage Return befehl kommt CR)? Neben den powermode Befehlen habe ich leider noch einen weiteren Befehl im Protokoll gefunden, der ein kleines 'p' in sich trägt. Wie adaptiere ich den Code von der Stackoverflow Seite auf mein Problem? Wie gesagt ich bearbeite diesen Teil des Projekts mit gefährlichem Halbwissen:-) Im Anhang findet ihr jetzt das komplette Protokoll. Danke für die Hilfe. Super Communitiy hier.
FaisalTU schrieb: > Im Anhang findet ihr jetzt das komplette Protokoll. Poste lieber noch mal dein jetziges Programm. Das von da oben war voller Fehler, die du hoffentlich korrigiert hast.
> Falls dieser dann vorhanden ist, soll er die 7 Zeichen danach einlesen Nein. er soll nicht 7 Zeichen einlesen. Er soll solange Zeichen einlesen und abspeichern, bis ein CR daherkommt. Erst danach hast du eine Chance, dass das was du bekommen hast auch tatsächlich eine Message ist, ob sie komplett ist oder nicht, kommt drauf an ob man mitten in die Übertragung eingestiegen ist oder ob man auch das erste Zeichen mitgekriegt hat. Das ist das was dein Protokoll dir als Vorgabe gibt. Halte dich daran und du hast weniger Probleme. > Wie gesagt ich bearbeite diesen Teil des Projekts mit gefährlichem Halbwissen:-) Das ist das eigentliche Problem. Seine Fähigkeiten im Programmieren kann man zwar ab einem gewissen Grad auch in einem Projekt voranbringen. Aber erst mal muss man auf diesen Level kommen. Wer bei 0 anfängt, hat in einem konkreten Projekt nichts verloren.
:
Bearbeitet durch User
Karl Heinz schrieb: > Er soll solange Zeichen einlesen und abspeichern, bis ein CR daherkommt. > Erst danach hast du eine Chance, dass das was du bekommen hast auch > tatsächlich eine Message ist, ob sie komplett ist oder nicht, kommt > drauf an ob man mitten in die Übertragung eingestiegen ist oder ob man > auch das erste Zeichen mitgekriegt hat. Dann müsste ich mehr Platz für den String anlegen. Muss ich das Abbruch Kriterium mit in die While Schleife mit einbinden? Wie schaut sowas dann aus? Karl Heinz schrieb im Beitrag #4058681: > avr305.h? > Wieso avr305.h? > > Du inkludierst IMMER#include <avr/io.h> Ich hab die Header Datei so übernommen da ich schon eine fertige Makefile habe für den Attiny25. Das Kompiliert soweit auch und habe damit kein Problem . Heruntermachen brauchste mich dafür nicht:-). Und ja ich bin sehr schlecht im Programmieren. Aber das musst du mir nicht sagen, wenn ich das schon erwähnt habe .
Hallo, Peter Dannegger (peda) hat eine "Software UART mit FIFO" implementiert, die wunderbar funktioniert. Auch kann man sie in andere Hochsprachen übersetzen. Beitrag "Re: Software UART mit FIFO" Ich verwende sie, neben Peter Danneggers Bootloader "fastboot 2", auf einem attiny85 mit 8MHz. Peter Dannegger "Software UART mit FIFO" habe ich dahingehend erweitert, dass sie bei 9600Bit/s 8/N/2 mit Timer1 und PCINT für beliebige RXD Eingänge auf einem attiny85 funktioniert. Natürlich muss man bei allen anderen Interrupt-Service Routinen auf kurze Ausführungszeiten achten und ich setze das globale Interrupt Flag über SEI sofort wieder am Anfang der anderen ISR-Routine. Atomarer Zugriff auf Variable mit mehr als 8 Bit muss man auch so kein wie möglich in CLI und SEI verpacken.
Hallo, noch eine Anmerkung zur Atmel AVR AP305 Umsetzung aus: https://github.com/Whistle/avr305 Hier blockiert natürlich die Sende- und Empfangsroutine und der gesamte Prozessablauf wartet bis das Zeichen (1 Startbit, 8 Datenbit, 1 Stoppbit) versendet wurde. Dafür wird natürlich der Software Uart Programmcode sehr klein gehalten.
FaisalTU schrieb: >> Du inkludierst IMMER#include <avr/io.h> > > Ich hab die Header Datei so übernommen ja, ich habs zu spät im GIT gesehen. In diesem Fall gehört dem, der die Vorlage gemacht hat, eine mit dem nassen Fetzen eine übergebraten. > Heruntermachen brauchste mich dafür nicht:-). Und ja ich bin sehr > schlecht im Programmieren. Aber das musst du mir nicht sagen, wenn ich > das schon erwähnt habe . Immer dasselbe. Ich kanns zwar nicht, will aber machen. Das funktioniert so nicht, hat noch nie funktioniert und wird auch nie funktionieren.
FaisalTU schrieb: > Karl Heinz schrieb: >> Er soll solange Zeichen einlesen und abspeichern, bis ein CR daherkommt. >> Erst danach hast du eine Chance, dass das was du bekommen hast auch >> tatsächlich eine Message ist, ob sie komplett ist oder nicht, kommt >> drauf an ob man mitten in die Übertragung eingestiegen ist oder ob man >> auch das erste Zeichen mitgekriegt hat. > > Dann müsste ich mehr Platz für den String anlegen. Musst du nicht notwendigerweise. Wenn du tatsächlich weisst, dass kein Kommando (zur Zeit) länger als 7 Zeichen sein wird (exklusive CR), dann legst du halt ein Array der Länge 8 an (wegen dem abschliessendem \0, damit daraus ein String wird). Einen Zähler zu machen, der mitzählt wieviele Zeichen bisher eingetrudelt sind und wenn der Zähler größer als 7 ist, dann nichts mehr ins Array speichern, ist ja jetzt nicht wirklich das grosse Problem. > Muss ich das Abbruch > Kriterium mit in die While Schleife mit einbinden? Wie schaut sowas dann > aus? Am besten machst du überhaupt keine while Schleife, weil das dein ganzes Programm blockiert.
:
Bearbeitet durch User
Karl Heinz schrieb: > In diesem Fall gehört dem, der die Vorlage gemacht hat, eine mit dem > nassen Fetzen eine übergebraten Wie meinst du das? Ist das etwa falsch? Karl Heinz schrieb: > Immer dasselbe. Ich kanns zwar nicht, will aber machen. > Das funktioniert so nicht, hat noch nie funktioniert und wird auch nie > funktionieren. Das Problem ist, dass das ein Teil meiner Bachelorarbeit ist, jedoch ein sehr kleiner, trotzdem wichtiger Teil. Es steht soweit alles, jedoch mag die Software nicht wirklich.
1 | static const char COMMAND[] = "pwrc000"; |
2 | |
3 | enum
|
4 | { SCAN, ONOFF }; |
5 | |
6 | int main |
7 | {
|
8 | int state = SCAN; |
9 | int idx = 0; |
10 | |
11 | while(1) { |
12 | c = read(); |
13 | |
14 | if(state == SCAN) { |
15 | if (c == COMMAND[idx]) { |
16 | idx++; |
17 | if(COMMAND[idx] == '\0') { |
18 | state = ONOFF; |
19 | }
|
20 | } else { |
21 | idx = 0; |
22 | if (c == COMMAND[idx]) { |
23 | idx++; |
24 | }
|
25 | }
|
26 | } else /* state == ONOFF */ { |
27 | if(c == '0') { |
28 | // DO OFF
|
29 | } else if(c == '1') { |
30 | // DO ON
|
31 | }
|
32 | |
33 | idx = 0; |
34 | state = SCAN; |
35 | }
|
36 | }
|
37 | }
|
Karl Heinz schrieb: > Am besten machst du überhaupt keine while Schleife, weil das dein ganzes > Programm blockiert. Du machst das so (ungetesteter Code)
1 | #define BUFFER_SIZE 10 // nicht kleckern. Klotzen!
|
2 | |
3 | char InputBuffer[BUFFER_SIZE]; |
4 | uint8_t BufferCnt; |
5 | |
6 | int main() |
7 | {
|
8 | |
9 | |
10 | ... Initialisierung |
11 | |
12 | BufferCnt = 0; |
13 | |
14 | while( 1 ) { |
15 | |
16 | c = readc(); |
17 | if( c != 0 ) { // ein Zeichen liegt vor |
18 | |
19 | if( c != '\n' ) { // war es kein CR? Dann ist die Nachricht noch |
20 | // nicht zu Ende. Zeichen speichern, wenn noch Platz ist
|
21 | if( BufferCnt < BUFFER_SIZE - 1 ) { |
22 | InputBuffer[BufferCnt] = c; |
23 | BufferCnt++; |
24 | }
|
25 | }
|
26 | |
27 | else { // es war ein CR. Theoritisch liegt ein Kommando vor |
28 | InputBuffer[BufferCnt] = '\0'; // erst mal einen richtigen String |
29 | // daraus machen.
|
30 | BufferCnt = 0; // beim nächsten Zeichen wieder von |
31 | // vorne weg in den Buffer schreiben
|
32 | |
33 | wenn geht, dann hier das Kommando irgendwo ausgeben lassen, |
34 | damit man mal sieht, ob die Kommunikation klappt! |
35 | Nichts ist schlimmer als das Stochern im Dunkeln! |
36 | |
37 | if( strcmp( InputBuffer, "Hallo" ) == 0 ) { |
38 | // es war das Kommando 'Hallo'
|
39 | }
|
40 | |
41 | else if( strcmp( InputBuffer, "Welt" ) == 0 ) { |
42 | // es war das Kommando Welt
|
43 | }
|
44 | }
|
45 | }
|
46 | |
47 | .... restliche Programmlogik |
48 | |
49 | }
|
50 | }
|
FaisalTU schrieb: > Das Problem ist, dass das ein Teil meiner Bachelorarbeit ist Autsch. Das wenn ich früher gesehen hätte, dann hätt ich mich verabschiedet. Ich mag es nicht, wenn jemand einen akademischen Grad für etwas kriegt, von dem er keine Ahnung hat.
FaisalTU, was Karl Heinz (kbuchegg) sagt, ist *.h Dateiendungen stehen für Header-Dateien. In *.h Datei stehen die Prototypen der Proceduren / Funktionen und allg. globale Definitionen wie Variable, Strukturen etc. In *.c Datei wird dann der Code nun implementiert. So dass man aus der einen Datei nun zwei machen würde und die *.c Datei im Makefile ablegt.
Karl Heinz schrieb: > Du machst das so (ungetesteter Code) Ihr seid die Besten hier. Danke dir. Ich versuch diesen Code mit eingefügter Programmlogik für ab und anschalten sowie die richtigen Kommandos demnächst aus, und sag Bescheid, wenn es geklappt hat.
Karl Heinz schrieb: > Autsch. > Das wenn ich früher gesehen hätte, dann hätt ich mich verabschiedet. > Ich mag es nicht, wenn jemand einen akademischen Grad für etwas kriegt, > von dem er keine Ahnung hat. Keine Sorge. Das ist nur ein Teil den ich persönlich mit eingefügt habe um eine bessere Note zu bekommen. Ich bekomme den Abschluss auch ohne dem :-).
Faisal Alam schrieb: > Karl Heinz schrieb: >> Du machst das so (ungetesteter Code) > > Ihr seid die Besten hier. Danke dir. Ich versuch diesen Code mit > eingefügter Programmlogik für ab und anschalten sowie die richtigen > Kommandos demnächst aus, und sag Bescheid, wenn es geklappt hat. Den wichtigsten Punkt hast du übersehen! Schaff dir eine Möglichkeit, wo du dir die Zeichen die reinkommen ausgeben lassen kannst! Nichts ist hier schlimmer als das Stochern im Nebel, das man nicht weiss, ob überhaupt das von der UART ankommt, was man denkt das ankommen sollte. Da gibt es viele Fehlerquellen!
Karl Heinz schrieb: > Faisal Alam schrieb: >> Karl Heinz schrieb: >>> Du machst das so (ungetesteter Code) >> >> Ihr seid die Besten hier. Danke dir. Ich versuch diesen Code mit >> eingefügter Programmlogik für ab und anschalten sowie die richtigen >> Kommandos demnächst aus, und sag Bescheid, wenn es geklappt hat. > > Den wichtigsten Punkt hast du übersehen! > > Schaff dir eine Möglichkeit, wo du dir die Zeichen die reinkommen > ausgeben lassen kannst! > > Nichts ist hier schlimmer als das Stochern im Nebel, das man nicht > weiss, ob überhaupt das von der UART ankommt, was man denkt das ankommen > sollte. Da gibt es viele Fehlerquellen! Ja werden ich auf jedenfall machen.
Uwe S. schrieb: > FaisalTU, > > was Karl Heinz (kbuchegg) sagt, ist *.h Dateiendungen stehen für > Header-Dateien. > In *.h Datei stehen die Prototypen der Proceduren / Funktionen und allg. > globale Definitionen wie Variable, Strukturen etc. > In *.c Datei wird dann der Code nun implementiert. > > So dass man aus der einen Datei nun zwei machen würde und die *.c Datei > im Makefile ablegt. Steht auf Github sogar in der Readme, dass es so wie es ist eigentlich nicht richtig ist ^^ FaisalTU, der Fehler ist stilistisch nicht funktionell.
Sorry muss das ganze hier noch mal rausholen. Ich bin mit der Arbeit jetzt fertig. Jedoch wollte ich jetzt eine Version mit einem Hardware Uart machen. Dafür habe ich einen Attiny2313 genommen. Die Library findet ihr im Anhang. Reicht es hierbei, die Funktion des Soft-uart(read()) durch das receive_uart() auszutauschen, um den gleichen Effekt zu bekommen? Grüße
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.