Envoyer Text à un LCD avec Firmata et VB.NET

Bonjour à tous,

J’essaie de commander un Arduino UNO ou autre à partir d’un programme VB.NET utilisant le protocol Firmata 2.4.4 .

Je me suis basé sur FirmataVB mais aussi sur http://www.imagitronics.org.

Pour la partie arduino, j’utilise le sketch StandardFirmata modifié à partir de ce lien LCD-Libraryfor-Snap4Arduino

J’arrive à:
-Me connecter à Arduino au travers d’un port com.
-Commander des sorties digitales On/Off.
-Lire des entrées digitales.
-Lire des entrées analogiques

Je voudrais:
-effacer un LCD.
-définir la position du curseur.
-envoyer un texte.

La function ‘void sysexCallback(byte command, byte argc, byte *argv)’ est modifiée ainsi:

    case ANALOG_MAPPING_QUERY:
      Firmata.write(START_SYSEX);
      Firmata.write(ANALOG_MAPPING_RESPONSE);
      for (byte pin = 0; pin < TOTAL_PINS; pin++) {
        Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
      }
      Firmata.write(END_SYSEX);
      break;
    
    //Ajout LCD
    case 0x08: // Print
      for (int c = 0; c < argc; c++) 
      {
        lcd.write(argv[c]);
      }
      break;
    case 0x09: // Clear
      lcd.clear();
      //lcd.print("This is a test !");
      break;
    case 0x0A: // Set Cursor
      lcd.setCursor(argv[0], argv[1]);
      break;

Bien sur, l’écran est configuré avec la bonne librairie et fonctionne .

Pour la partie VB.NET:
J’ai tenté d’ajouter les commandes Sysex.

    'Add LCD commands
    ' Send an LCD_WRITE Sysex message
    <Description("Sends an End Sysex message")> _
    Public Sub LcdWriteSysex(ByVal text As Integer)
        Dim message(2) As Byte
        'message(0) = LCD_WRITE Or (text And &HF)
        'message(1) = yLCDCursor And &H7F
        'message(2) = (yLCDCursor >> 7) And &H7F
        Try
            _SerialPort.Write(message, 0, 3)
            Debug.Print("Write Digital data:" & message(1))
        Catch ex As Exception
            MessageBox.Show("DigitalWrite communication error." & vbCrLf & ex.ToString())
        End Try

        message = Nothing
    End Sub
    ' Send an LCD_CLEAR Sysex message
    <Description("Sends LcdClear Sysex message")> _
    Public Sub LcdClearSysex()
        Dim message() As Byte = {0}
        message(0) = LCD_CLEAR
        Try
            _SerialPort.Write(message, 0, 1)
            Debug.Print("LcdClear Sysex:" & message(0))
        Catch ex As Exception
            MessageBox.Show("LcdClear Sysex communication error." & vbCrLf & ex.ToString())
        End Try
        message = Nothing
    End Sub
    ' Send an LCD_SETCURSOR Sysex message
    <Description("Sends LcdSetCursor Sysex message")> _
    Public Sub LcdSetCursorSysex(xLCDCursor As Integer, yLCDCursor As Integer)
        Dim message(2) As Byte
        message(0) = LCD_SETCURSOR Or (xLCDCursor And &HF)
        message(1) = yLCDCursor And &H7F
        message(2) = (yLCDCursor >> 7) And &H7F
        Try
            _SerialPort.Write(message, 0, 3)
            Debug.Print("LcdClear Sysex:" & message(0))
        Catch ex As Exception
            MessageBox.Show("LcdClear Sysex communication error." & vbCrLf & ex.ToString())
        End Try
        message = Nothing
    End Sub
    'Add LCD commands

et je les utilise ainsi:

    Private Sub ButtonClearLCD_Click(sender As System.Object, e As System.EventArgs) Handles ButtonClearLCD.Click
        Try
            ard.StartSysex()
            ard.LcdClearSysex()
            ard.EndSysex()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    End Sub
    Private Sub ButtonSetcursor_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSetcursor.Click
        Try
            ard.StartSysex()
            ard.LcdSetCursorSysex(10, 1)
            ard.EndSysex()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub
    Private Sub ButtonSendText_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSendText.Click
        If TextBox1.Text <> "" Then
            Try
                ard.StartSysex()
                ard.LcdWriteSysex("Hello World")
                ard.EndSysex()
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End If
    End Sub

Merci de votre aide pour réécrire les commandes Sysex pour le LCD

StandardFirmataWithLCDStepper.ino (27.1 KB)

FirmataLCDTest.zip (95 KB)

Bonjour,
les éléments de ton tableau message(), dans le Sub LcdWriteSysex, sont en commentaires. Est-ce voulu ?

trimarco232:
Bonjour,
les éléments de ton tableau message(), dans le Sub LcdWriteSysex, sont en commentaires. Est-ce voulu ?

Oui , justement c'est la partie que je n'arrive pas à écrire!

J'ai oublié de préciser les constantes des nouveaux messages Sysex:
'LCD adds
Public Const LCD_WRITE As Byte = &H8
Public Const LCD_CLEAR As Byte = &H9
Public Const LCD_SETCURSOR As Byte = &HA

je n'ai regardé qu'en diagonale discontinue, donc pardon pour les questions est idiotes :

  • parviens-tu à faire une appli vb net simple comme écriture d'un octet vers arduino et réception de l'octet en réponse de l'arduino (cela te mettrait sur les rails) ?

trimarco232:
je n'ai regardé qu'en diagonale discontinue, donc pardon pour les questions est idiotes :

  • parviens-tu à faire une appli vb net simple comme écriture d'un octet vers arduino et réception de l'octet en réponse de l'arduino (cela te mettrait sur les rails) ?

Bien sure, le code fonctionne trés bien déjà puisque je commande les pins digitales en entrée ou sortie, la pina analogiques en entrées . Voir le détail dans le post 1.

Personne ne peux m'aider SVP ?

Pas de souci.

Peux-tu nous communiquer les code que tu utilises pour :

  1. envoyer un octet en vb net
  2. le lire en arduino
  3. le retransmettre depuis arduino (pourquoi pas après modif)
  4. le lire vb net
    Nous partirons de là pour aller vers le but.

Par ailleurs, concernant Ta fonction LcdWriteSysex, tu utilises SerialPort.Write(message, 0, 3) pour envoyer "hello etc" : cette méthode est d'avantage prévue pour envoyer des octets (ceux présents dans le tableau message) que pour envoyer du texte.
Je pense donc qu'il te reste quelques notions à acquérir pour pouvoir mener à bien ton projet ...
... pareil pour moi, mais j'ai "un peu" d'avance, et je peux t'aider si tu y mets du tien.

trimarco232:

Quand je dis que le code fonctionne déjà très bien , ce n'est pas le cas bien sure de l'ajout des messages Sysex vers le LCD .

zut nos messages se sont croisés ...

trimarco232:
Pas de souci.

Peux-tu nous communiquer les code que tu utilises pour :

  1. envoyer un octet en vb net
  2. le lire en arduino
  3. le retransmettre depuis arduino (pourquoi pas après modif)
  4. le lire vb net
    Nous partirons de là pour aller vers le but.

Par ailleurs, concernant Ta fonction LcdWriteSysex, tu utilises SerialPort.Write(message, 0, 3) pour envoyer “hello etc” : cette méthode est d’avantage prévue pour envoyer des octets (ceux présents dans le tableau message) que pour envoyer du texte.
Je pense donc qu’il te reste quelques notions à acquérir pour pouvoir mener à bien ton projet …
… pareil pour moi, mais j’ai “un peu” d’avance, et je peux t’aider si tu y mets du tien.

  1. Tu as le code VB complet dans le fichier Arduino.vb
  2. Le code initial est le fichier StandardFirmata.ino de la version 2.4.4. Je l’ai modifié et il est devenu ‘StandardFirmataWithLCDStepper.ino’ voir post 1
    3.4. voir Arduino.vb

J’ai tenté d’utiliser ‘SerialPort.Write(message, 0, 3)’ comme dans d’autre parties du code effectivement, et surement mal.
Je rejoins la class Arduino.vb

Je démarre la connexion ainsi:

Dim ard As Arduino
    Dim ComPortIsReady As Boolean = False
    Dim D8OnOff As Boolean = False

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        For Each port In System.IO.Ports.SerialPort.GetPortNames()
            If port = "COM3" Then
                ComPortIsReady = True
                Exit For
            End If
        Next
        If ComPortIsReady = True Then
            ard = New Arduino("COM3", 57600, True, 8000, FirmataLCDTest.Arduino.Board.DIECIMILA)
            ard.WithVersionReceieveEvents = False
            ard.WithDigitalReceiveEvents = False
            ard.WithAnalogReceiveEvents = False
      [color=red]      'ard.pinMode(6, Arduino.SERVO) 'imposta in pin 10 per pilotare un servo motore
            'ard.analogWrite(6, 10) 'invia un comando
            'ard.pinMode(13, Arduino.OUTPUT) 'imposta il pin 13 in scrittura
            'ard.digitalWrite(13, Arduino.HIGH) 'accende il led
            'ard.DigitalPortReport(11, 1)
            'ard.pinMode(11, Arduino.INPUT) 'imposta il pin 11 in lettura
            'ard iValoreLetto As Integer = ard.digitalRead(11) 'legge il valore[/color]
            Timer1.Enabled = True
        Else
            MessageBox.Show("Arduino isn't connected !")
        End If
    End Sub

Les lignes commentées sont les différentes commandes possibles !!!

Arduino.zip (6.08 KB)

ok,

il y a 2 choses :

A) tu ajoutes des fonctionnalités supplémentaires à un protocole de communication existant : il faut définir le complément de protocole, et t'assurer de sa compatibilité avec l'existant
peux-tu me faire une description complète de ce protocole ?

B) il faut compléter les programmes selon ma classification empirique : 1, 2, 3, 4

Concernant le 1) déjà évoqué et la fonction SendString(), tu as :

Dim message(3) As Byte
message(0) = STRING_DATA
'message(1) = yLCDCursor And &H7F
'message(2) = (yLCDCursor >> 7) And &H7F
For i = 0 To text.Length
message(1) = text(i) And &H7F
message(2) = (text(i) >> 7) And &H7F
Next

il faudrait quelque chose du genre :

Dim message(2*text.Length + 3) As Byte      ' la taille du tableau en nombre de bytes
message(0) = yLCDCursor And &H7F             ' évoque le LCD
message(1) = (yLCDCursor >> 7) And &H7F
message(2) = STRING_DATA                       ' dit que du texte suit
For i = 0 To text.Length -1
message(2*1 + 3) = asc(mid(text, i)) And &H7F   ' trouver et coder
message(2*i + 4) = asc(mid(text, i)) >> 7) And &H7F   ' caractère envoyé en 2 bytes
Next

à ta disposition pour en discuter ...

Le protocol firmata est défini ici V2.3ProtocolDetails - Firmata

Il est moins complet que la dernière version existante , la 2.4.4 .

Comme on peux le voir dans le code arduino, l’ajout est celui-ci:

    //Ajout LCD
    case 0x08: // Print
      for (int c = 0; c < argc; c++) 
      {
        lcd.write(argv[c]);
      }
      break;
    case 0x09: // Clear
      lcd.clear();
      //lcd.print("This is a test !");
      break;
    case 0x0A: // Set Cursor
      lcd.setCursor(argv[0], argv[1]);
      break;

VB doit donc envoyer le code :
&H8 ou 8 decimal pour envoyer un texte
&H9 ou 9 decimal pour envoyer une demande d’effacement
&HA ou 10 decimal pour preciser la position du curseur !

je comprend tes points 1 et 2 , mais 3 et 4 ne sont pas accessibles directement avec le code actuel, mais cela m’intéresse .

Bon je test la partie VB.

    Public Sub LcdWriteSysex(text As String)
        Dim message(2 * text.Length + 3) As Byte      ' la taille du tableau en nombre de bytes
        message(0) = yLCDCursor And &H7F             ' évoque le LCD
        message(1) = (yLCDCursor >> 7) And &H7F
        message(2) = STRING_DATA                       ' dit que du texte suit
        For i = 0 To text.Length - 1
            message(2 * 1 + 3) = Asc(Mid(text, i)) And &H7F   ' trouver et coder
message(2*i + 4) = asc(mid(text, i)) >> 7) And &H7F   ' caractère envoyé en 2 bytes
        Next
        Try
            _SerialPort.Write(message, 0, 3)
            Debug.Print("Write Digital data:" & message(1))
        Catch ex As Exception
            MessageBox.Show("DigitalWrite communication error." & vbCrLf & ex.ToString())
        End Try

        message = Nothing
    End Sub

Dans le code VB, la ligne 'message(2*i + 4)........' rencontre une erreur
Je pense que l'on ne devrait pas définir la position x et y du curseur dans la commande qui envoit le texte mais plutôt dans celle qui définit justement la position du curseur , soit:
Public Sub LcdSetCursorSysex(xLCDCursor As Integer, yLCDCursor As Integer)
...

Qui elle aussi est à réécrire !!!

Il y avait un caractère caché qui posait problème !
Le code VB que je test est donc:

  Public Sub LcdWriteSysex(text As String, yLCDCursor As Integer)
        Dim message(2 * text.Length + 3) As Byte      ' la taille du tableau en nombre de bytes
        message(0) = yLCDCursor And &H7F             ' évoque le LCD
        message(1) = (yLCDCursor >> 7) And &H7F
        message(2) = STRING_DATA                       ' dit que du texte suit
        For i = 0 To text.Length - 1
            message(2 * 1 + 3) = Asc(Mid(text, i)) And &H7F   ' trouver et coder
            message(2 * i + 4) = Asc(Mid(text, i) >> 7) And &H7F ' caractère envoyé en 2 bytes
        Next
        Try
            _SerialPort.Write(message, 0, 3)
            Debug.Print("Write Digital data:" & message(1))
        Catch ex As Exception
            MessageBox.Show("DigitalWrite communication error." & vbCrLf & ex.ToString())
        End Try

        message = Nothing
    End Sub

Et j’appelle donc la commande ainsi:

    Private Sub ButtonSendText_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSendText.Click
        If TextBox1.Text <> "" Then
            Try
                ard.StartSysex()
                ard.LcdWriteSysex(TextBox1.Text, 2)
                ard.EndSysex()
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End If
    End Sub

A mon avis il y a une faute de frappe ici:
message(2 * 1 + 3) = Asc(Mid(text, i)) And &H7F ' trouver et coder
Ce devrait être
message(2 * i + 3) = Asc(Mid(text, i)) And &H7F ' trouver et coder

kamill:
A mon avis il y a une faute de frappe ici:
message(2 * 1 + 3) = Asc(Mid(text, i)) And &H7F ' trouver et coder
Ce devrait être
message(2 * i + 3) = Asc(Mid(text, i)) And &H7F ' trouver et coder

Merci kamil, je regarde ça de suite

Je pense que la ligne qui suit ne sera pas bonne , puisque en troisième position on doit avoir la taille message, c'est ça ?
_SerialPort.Write(message, 0, 3)

Ce serait alors:
_SerialPort.Write(message, 0, 2 * text.Length + 3) ???

Le code me retourne l'erreur:
Argument 'Start' must be greater than zero.

On dirait que mon code ne lit pas la valeur de TextBox1.text!
Modifié ainsi, je n’ai plus d’erreur , mais rien de nouveau sur l’écran LCD !

        If TextBox1.Text <> "" Then
            'MessageBox.Show(TextBox1.Text)
            Try
                Dim text As String = "Hello World"
                ard.StartSysex()
                ard.LcdWriteSysex(text, 2)
                ard.EndSysex()
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End If

J'ai trouvé un sujet intéressant ici

Si cela peut aider ?