- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 9 von 9

Thema: Variablenübergabe zwischen RS232 und Atmega32

  1. #1

    Blinzeln Variablenübergabe zwischen RS232 und Atmega32

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hi liebe Forengemeinde, nun ist wieder ein Punkt erreicht andem ich eure Unterstützung benötige.
    Für meinen Aquarien-/Terrarien-/Paludariumcontroller baue ich gerade ein kleines Interfaceprogramm mit VB2010Express, mit dessen Hilfe ich auch vom PC aus Einstellungen ändern möchte und diverse Sensorwerte Loggen will.
    Meine Verbindung vom Atmega zur RS232 Schnittstelle funktioniert Hardwareseitig (getestet mit Hterminal), Sourcecode für UART von Peters lib.

    Ich Frage mich nur wie ich das Programm so Grundsätzlich aufbauen muss, wenn ich z.b. an den uC über UARTden Befehl "Einstellungen einlesen" Sende und mir der uC die Variablen für die Einstellungen nacheinander an den PC Senden soll, da das meine ersten Versuche mit der RS232 Schnitstelle sind.

    Stehe grad echt auf dem Schlauch

    PHP-Code:
    uart_getc();
            if ( 
    UART_NO_DATA )
            {
                
    /* 
                 * no data available from UART 
                 */
            
    }
            else
            {
                
    /*
                 * new data available from UART
                 * check for Frame or Overrun error
                 */
                
    if ( UART_FRAME_ERROR )
                {
                    
    /* Framing Error detected, i.e no stop bit detected */
                    
    uart_puts_P("UART Frame Error: ");
                }
                if ( 
    UART_OVERRUN_ERROR )
                {
                    
    /* 
                     * Overrun, a character already present in the UART UDR register was 
                     * not read by the interrupt handler before the next character arrived,
                     * one or more received characters have been dropped
                     */
                    
    uart_puts_P("UART Overrun Error: ");
                }
                if ( 
    UART_BUFFER_OVERFLOW )
                {
                    
    /* 
                     * We are not reading the receive buffer fast enough,
                     * one or more received character have been dropped 
                     */
                    
    uart_puts_P("Buffer overflow error: ");
                }
                
    /* 
                 * send received character back
                 */
                
    uart_putc( (unsigned char));
            } 
    Code in "C"

    Lieben Dank schonmal.
    Geändert von Natureengeneer (27.09.2012 um 22:55 Uhr)

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    19.06.2004
    Alter
    51
    Beiträge
    66
    Hi,


    Du solltest Dir zunächst eine Grundsätzliche Frage stellen: sollen die Daten zwischen Deinem Board und dem PC binär oder im ASCII Format übertragen werden?


    a) binär
    Bei einer binären Übertragung kannst Du viel mehr Messwerte pro Sekunde übertragen. Auch die Befehle vom PC zum Board sind einzelne Opcodes (Bytes). Benötigt allerdings eine spezielle Software auf der PC Seite die Du selbst schreiben musst.


    b) im ASCII Format
    Hierbei werden Messwerte und Befehle zum Board im Textformat übertragen. Dies hat den Vorteil, dass Du auch Hyperterminal zur Kommunikation nutzen kannst. Nachteil: viel langsamer als binär.


    Grundsätzlich:
    Deine Idee mit dem Echo auf Seiten des Boards zu implementieren ist gut. So kannst Du auf der PC Seite gleich sehen, ob die Bytes/Zeichen, die Du zum Board geschickt hast, korrekt angekommen sind.


    Da Du offensichtlich zu dem Thema "Datenaustausch zwischen PC und Board" noch nicht viel Erfahrung hast, empfehle ich Dir Variante "b" - alleine schon um Hyperterminal nutzen zu können.


    Wenn Variante "b" genutzt werden soll:
    Es ist üblich, Kommandos vom PC an das Board mit "ENTER" abzuschließen, d.h. der ASCII Code 13 wird am Ende des Befehles gesendet.


    D.h. auf Deinem Board müsstest Du auf das Byte 13 warten und erst dann die bis dahin empfangenen Zeichen auf einen bekannten Befehl hin zu vergleichen.


    Beispiel eines Pseudocodes für das Board um Befehle zu erkennen:


    Code:
    if (<Zeichen empfangen>==TRUE)
    {
      SendeZeichenkette (<Empfangenes Zeichen>); // ECHO
      if (<Empfangenes Zeichen>!=13)
      { 
        // KEIN ENTER EMPFANGEN, ALSO BUCHSTABEN WEITER SAMMELN:
        <Empfangene Zeichenkette> = <Empfangene Zeichenkette> + <Empfangenes Zeichen>;
      }
      else
      { 
        // ENTER EMPFANGEN (Achtung: das ENTER wird nicht zur <Empfangenen Zeichenkette> hinzugefügt!
        if (<Empfangene Zeichenkette>=="GET TEMP")
        {
          // Temperatur abfrage: d.h. Temperatur an den PC senden
          SendeZeichenkette ("TEMP=");
          SendeZeichenkette (itoa(iTemperature));
          SendeZeichenkette (13);
          <Empfangene Zeichenkette> = "";
        }
        else
        if (<Erste Neun Zeichen der empfangenen Zeichenkette>=="SET TEMP ")
        {
          <Parameter Zeichenkette> = <von der empfangenen Zeichenkette die Zeichen ab der zehnten Stelle>;
          atoi (<Parameter Zeichenkette>,&iParameterzahl); // ASCII Zahl in binär Zahl umwandeln. Bsp."23" in 23
          if (iParameterzahl>=15) AND (iParameterzahl<=20)
          {
            SetzeTemperatur (iParameterzahl);
            SendeZeichenkette ("OK");
          }
          else
          {
            SendeZeichenkette ("INVALID VALUE FOR SET TEMP. VALID VALUE = 15 .. 20");
          }
          SendeZeichenkette (13);
          <Empfangene Zeichenkette> = "";
        }
        else
        {
          SendeZeichenkette ("INVALID COMMAND.");
          SendeZeichenkette (13);
          <Empfangene Zeichenkette> = "";
        }
      }
    }
    Beachte jedoch: der obige Pseudocode enthält noch keine Überprüfung ob die empfangenen Zeichen noch in den Empfangspuffer (<Empfangene Zeichenkette>) hineinpassen.

    Ich empfehle Dir dringend, dies hier aufmerksam durch zu lesen:

    http://www.rn-wissen.de/index.php/Av...rstellung_in_C
    http://www.rn-wissen.de/index.php/C-...ichenketten.29

    Dort findest Du einige Hinweise zum Thema Strings in C.
    Geändert von Chris266 (25.09.2012 um 06:19 Uhr)

  3. #3
    Vielen Dank schonmal für die Tipps ich verstehe jetzt was ich zu tun habe nur happerts ein bisschen an der Umsetzung.
    PHP-Code:
    int index=0;
        
    char ch[20];

    while(
    c!=13)
               {
                    
    ch[index]=c;
                    
    index++;   
               }            
                if (
    c==13)
                {
                    
    index 0;
                } 
    Mein Versuch aber irgendwie machts ned so wie es soll

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Guten Morgen,

    Zitat Zitat von Natureengeneer Beitrag anzeigen
    while(c!=13)
    und

    Zitat Zitat von Natureengeneer Beitrag anzeigen
    if (c==13)
    schließt sich aus, das kann so nichts werden.

    Viele Grüße
    Andreas

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    19.06.2004
    Alter
    51
    Beiträge
    66
    Dein Ansatz gefällt mir.
    Es freut mich, dass Du selbst das Problem lösen willst, statt fertige Codeschnipsel
    einzusetzen.


    Deinem Code fehlt noch der Stringvergleich, d.h. die Prüfung auf empfangene Befehle.
    Um Dir die Suche zu verkürzen: schau mal bei "strcmp" nach. Diese C Funktion vergleicht zwei Strings miteinander.


    In Deinem Code hast Du "index" korrekt angewendet, lediglich eines hast Du übersehen:
    C Strings sind Nullterminiert. D.h. am Ende eines jeden Strings muss das Byte 0 stehen.


    Diese 0 muss selbstverständlich nicht immer am Ende eines Strings stehen, da Du bis zum Eintreffen der ENTER Taste (13) die Variable "index" nutzt, um die Stringlänge zu indizieren.


    Deshalb ist es bei Deinem Codebeispiel erst dann notwendig, das Byte 0 an das Ende des Strings zu hängen, bevor Du die Funktion strcmp nutzt (denn diese Funktion verwendet nicht wie Du einen Index für die Identifikation der Stringlänge sondern sucht nach dem Byte 0).


    Deshalb wäre es genug, wenn Du nach dem Empfang von 13 das 0 Byte an Deinen String anhängst.
    Beispielsweise so:


    if (c==13)
    {
    ch[index]=0;
    index=0;
    }


    In die selbe if Bedingung müsstest Du nun den empfangenen String auf bekannte Befehle hin überprüfen.
    Hierfür kannst Du strcmp nutzen. Ein Beispiel:


    if (strcmp (ch,"GET TEMP")==0)
    {
    // Temperatur soll angefragt werden
    }


    Nähere Infos zu strcmp findest Du im Internet.


    Ich vermisse in Deinem Code noch das Setzen von "c". D.h. "c" muss ja das empfangene Byte enthalten, was über die serielle Schnittstelle reinkommt.
    Dies machst Du selbstverständlich in der While Schleife.


    Bevor die While Schleife beginnt, solltest Du "c" unbedingt auf einen Wert ungleich 13 setzen, sonst wird beim nächsten Durchlauf nicht mehr in die While Schleife gesprungen, da "c" ja noch vom letzten Durchlauf 13 enthält.


    Das "if (c==13)" kannst Du Dir eigentlich sparen, denn c ist immer 13, wenn die While Schleife verlassen wird (sofern Du kein break einsetzt).
    Dein Compiler wird diese Zeile ohnehin löschen sofern er kein break in der While Schleife findet (die sogenannte Code Optimierung).


    Wenn Du Deinen Code sicherer machen möchtest: sei so gut und prüfe die Anzahl der Empfangenen Zeichen auf die Anzahl der Zeichen, die in Deinen String "ch" hineinpassen.
    Wie ich sehe hat dein Array/String platz für 19 Zeichen (das 20. enthält später das Byte mit dem Wert 0!).
    ACHTUNG: die Zählung beginnt bei 0! D.h. index darf Werte von 0 bis einschließlich 19 annehmen.

    Noch ein Hinweis zu Deiner While Schleife:
    Du verwendest eine While Schleife zum Abfragen auf das Eintreffen der ENTER Taste.
    Dies würde bedeuten, dein Prozessor ist solange mit nichts anderes beschäftigt als Zeichen zu empfangen, bis die ENTER Taste eintrifft.
    Ansich nichts schlechtes, sofern Dein Prozessor keine Ausgänge ansteuert, wie beispielsweise die Aquarium Heizung.
    D.h. solange die "13" nicht empfangen wurde, bleiben alle Ausgänge wie sie waren.
    Sofern der Prozessor aber AUCH automatisch / selbstständig die Heizung oder Pumpe ein/ausschalten soll, ist diese vorgehensweise nicht klug.

  6. #6

    Ja vielen Herzlichen Dank für diese tollen Informationen

    Es läuft!

    Hier mal nen Beispiel falls jemand das gleiche Prob hat.

    C Code:
    PHP-Code:
    int index=0;
        
    char ch[19];
    uart_getc();
            if ( 
    UART_NO_DATA )
            {
                
    /* 
                 * no data available from UART 
                 */
            
    }
            else
            {
                
    /*
                 * new data available from UART
                 * check for Frame or Overrun error
                 */
                
    if ( UART_FRAME_ERROR )
                {
                    
    /* Framing Error detected, i.e no stop bit detected */
                    
    uart_puts_P("UART Frame Error: ");
                }
                if ( 
    UART_OVERRUN_ERROR )
                {
                    
    /* 
                     * Overrun, a character already present in the UART UDR register was 
                     * not read by the interrupt handler before the next character arrived,
                     * one or more received characters have been dropped
                     */
                    
    uart_puts_P("UART Overrun Error: ");
                }
                if ( 
    UART_BUFFER_OVERFLOW )
                {
                    
    /* 
                     * We are not reading the receive buffer fast enough,
                     * one or more received character have been dropped 
                     */
                    
    uart_puts_P("Buffer overflow error: ");
                }
                
    /* 
                 * send received character back
                */ 
               
    uart_putc( (unsigned char));
               
               if((
    unsigned char)c!=13)
               {
                    
    ch[index]=c;
                    
    index++;   
               }            
                else
                {
                    
    ch[index]=0;
                    
    index 0;
                    if (
    strcmp (ch,"TEMP1")==0)
                    {
                        
    // Temperatur soll angefragt werden
                        
    uart_puts("Temperatur1=..........\n");
                    }
                    if (
    strcmp (ch,"TEMP2")==0)
                    {
                        
    // Temperatur soll angefragt werden
                        
    uart_puts("Temperatur2=..........\n");
                    }
                    if (
    strcmp (ch,"PH")==0)
                    {
                        
    // Temperatur soll angefragt werden
                        
    uart_puts("PH=..........\n");
                    }
                    if (
    strcmp (ch,"HUMIDITY")==0)
                    {
                        
    // Temperatur soll angefragt werden
                        
    uart_puts("Humidityr=..........\n");
                    }
                    
    ch[0]=0;
                    
                    
                    
                } 
    Geändert von Natureengeneer (27.09.2012 um 20:40 Uhr)

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    19.06.2004
    Alter
    51
    Beiträge
    66
    Das ist ja großartig.

    Ich möchte Dich noch auf ein paar Dinge hinweisen, wenn Du Wert auf ein stimmiges Programm legst (zumal Du Deinen Code auch anderen hier zur Verfügung stellst):

    a) Im Falle eines Fehlers, beispielsweise UART_BUFFER_OVERFLOW, UART_OVERRUN_ERROR, UART_FRAME_ERROR wird dessen Wert (inkl. den UART_BUFFER... Bits) nochmals an den PC gesendet (Stichwort "Echo").
    b) dein Prozessor ist unnötig belastet: er vergleicht die bisher empfangene Zeichenkette jedesmal wenn ein einzelnes Zeichen empfangen wurde. D.h. er wird einen Befehl zwei mal ausführen auch wenn Du kein ENTER gedrückt hast (aber nur wenn die Zeichenlänge identisch ist mit dem zuvor abgesetzten Befehl ist, bsp. TEMP1 und TEMP2. Mach Dir bitte die Mühe, und überprüfe den empfangenen String erst dann wenn tatsächlich ENTER empfangen wurde (zumal Du Deinen Code hier als Beispiel veröffentlicht hast)

    Ich mag an dieser Stelle etwas pingelig klingen, aber glaub mir, viele unvorhergesehene Verhaltensweisen eines Roboters oder einer Steuerung haben mit unsachgemäßer Programmierung zu tun. Nicht um sonst gibt es den "Programmierer" als Beruf mit entsprechender Ausbildung.

    Für ein solch' kleines Projekt ist es ggf. noch verschmerzbar, aber spätestens wenn es um das automatische Füttern Deiner Fische geht (wenn Du beispielsweise 3 Wochen in Urlaub bist), wäre es mehr als tragisch wenn deine Fische verhungern oder verkocht sind, weil die Heizung zu hoch heizt.

    Die Erfahrung zeigt: was schief gehen kann, passiert auch. Es ist nur eine Frage der Wahrscheinlichkeit wann ein Bug im Programmcode zum tragen kommt.

    Falls Du mir nicht glaubst, versuche folgendes:

    a) sende an dein Board "TEMP1" und drücke ENTER
    b) sende den Buchstaben "T" an Dein Board und es wird mit "Temperatur1=.......\n" antworten, noch bevor Du ENTER gedrückt hast

    Sei so gut und mache Deine "if (strcmp" Anweisungen bitte in die Klammer von "if ((unsigned char)c==13)" hinein.

    Wenn Du noch Fragen zum Code hast, poste einfach. Ich schau mir den gerne nochmal an.
    Geändert von Chris266 (27.09.2012 um 19:00 Uhr)

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    19.06.2004
    Alter
    51
    Beiträge
    66
    Möglicherweise habe ich etwas übersehen (wer schaut mal drüber?), aber so gefällt es besser:
    Code:
    int index=0;
    char ch[19];
    
    while (1)
    {
      c = uart_getc();
      if ( c & UART_NO_DATA )
      {
        /* 
         * no data available from UART 
         */
      }
      else
      {
        /*
         * new data available from UART
         * check for Frame or Overrun error
         */
        if ( c & UART_FRAME_ERROR )
        {
          /* Framing Error detected, i.e no stop bit detected */
          uart_puts_P("UART Frame Error: ");
          ch[0]=0;
          index=0;
        }
        else
        if ( c & UART_OVERRUN_ERROR )
        {
          /* 
           * Overrun, a character already present in the UART UDR register was 
           * not read by the interrupt handler before the next character arrived,
           * one or more received characters have been dropped
           */
          uart_puts_P("UART Overrun Error: ");
          ch[0]=0;
          index=0;
        }
        else
        if ( c & UART_BUFFER_OVERFLOW )
        {
          /* 
           * We are not reading the receive buffer fast enough,
           * one or more received character have been dropped 
           */
          uart_puts_P("Buffer overflow error: ");
          ch[0]=0;
          index=0;
        }
        else
        {
          /* 
           * send received character back
           */ 
          uart_putc( (unsigned char)c );
               
          if((unsigned char)c!=13)
          {
            ch[index]=c;
            index++;   
          }            
          else
          {
            ch[index]=0;
            index = 0;
            if (strcmp (ch,"TEMP1")==0)
            {
              // Temperatur soll angefragt werden
              uart_puts("Temperatur1=..........\n");
            }
            else
            if (strcmp (ch,"TEMP2")==0)
            {
              // Temperatur soll angefragt werden
              uart_puts("Temperatur2=..........\n");
            }
            else
            if (strcmp (ch,"PH")==0)
            {
              // Temperatur soll angefragt werden
              uart_puts("PH=..........\n");
            }
            else
            if (strcmp (ch,"HUMIDITY")==0)
            {
              // Temperatur soll angefragt werden
              uart_puts("Humidityr=..........\n");
            }    
            ch[0]=0;
          }             
        }
      } 
    }
    PS: es fehlt immernoch die Abfrage, ob die Anzahl der Empfangenen Zeichen länger als 18 sind. Das 19. ist das "0" Byte.
    Geändert von Chris266 (27.09.2012 um 19:18 Uhr)

  9. #9

    Lächeln

    Danke Danke habe den Fehler Korrigiert. Habs auch oben abgeändert. Die Abfrage ob der String länger ist bau ich dann später noch ein.

    In VB2010 habe ich das Senden eines Befehls so angestellt:

    Verbindungsbutton RS232:
    PHP-Code:
    Private Sub Button2_Click(sender As System.ObjectAs System.EventArgsHandles Button2.Click
            
    Try
                
    SerialPort1.PortName TextBox12.Text
                SerialPort1
    .BaudRate TextBox13.Text
                SerialPort1
    .DataBits 8
                SerialPort1
    .StopBits IO.Ports.StopBits.One
                SerialPort1
    .Parity IO.Ports.Parity.None
                SerialPort1
    .Handshake IO.Ports.Handshake.None
                SerialPort1
    .Open()
                
    Button2.Enabled False
                Button1
    .Enabled True
                Button3
    .Enabled True
                Button4
    .Enabled True
                Button5
    .Enabled True
                Button6
    .Enabled True
                Button7
    .Enabled True
                ProgressBar1
    .Value 100
                MsgBox
    ("Connected")
            Catch 
    ex As Exception
                ProgressBar1
    .Value 0
                MsgBox
    ("Connection Error 001")
            
    End Try
        
    End Sub 

    SendeButton:
    PHP-Code:
    Private Sub Button7_Click(sender As System.ObjectAs System.EventArgsHandles Button7.Click
            Dim buffer
    (200) As Byte
            Dim offset 
    As Integer
            Dim count 
    As Integer
            Dim returnValue 
    As Integer
            offset 
    0
            count 
    17
            SerialPort1
    .Write(vbCr)
            
    SerialPort1.Write("TEMP1")
            
    SerialPort1.Write(vbCr)
            
    System.Threading.Thread.Sleep(1000)
            
    Dim IncommingData SerialPort1.ReadExisting   
            TextBox15
    .Text IncommingData
     End Sub 
    Geändert von Natureengeneer (28.09.2012 um 01:41 Uhr)

Ähnliche Themen

  1. Atmega32 zwischen GPS-Modul und PC über RS232 . Brauche Hilfe :)
    Von da_miez3 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 14.04.2012, 18:33
  2. UART zwischen Atmega32 und ATmega8
    Von Lunarman im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 07.06.2007, 17:22
  3. Kommunikation zwischen C++ und ATMega32 (realisieren??)
    Von strunz im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 16
    Letzter Beitrag: 21.04.2006, 06:37
  4. [ERLEDIGT] Übertragung von Daten zwischen Atmega32 und Atmega128
    Von OBI im Forum AVR Hardwarethemen
    Antworten: 0
    Letzter Beitrag: 11.12.2004, 13:41
  5. Variablenübergabe in Funktion
    Von wolf4124 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 19.08.2004, 19:25

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests