Liaison Excel Arduino

Bonjour tout le monde ! je suis débutante en excel donc je demande votre aide !

J'ai un fichier excel avec une macro qui me donne des résultats sous formes de tableau de valeurs de x=.. et y=...

je veux transférer ces données à ma carte arduino pour pouvoir simuler mon programme

En fait l'idée est la suivante : deux moteurs seront liés à l'arduino et 2 leds aussi liés à l'arduino

si x=2 et y=3 (à partir de l'excel) par exemple les 2 moteurs vont tourner à droite et une led va clignoter 2 fois et l'autre va clignoter 3 fois.

mon tableau est sous dessus sur l'image

les lignes et les valeurs de tableau peuvent être modifiées

excel

Bonjour,

est-ce que tu veux une liaison directe entre ton fichier excel et ton arduino ?

ou bien seulement injecter les valeurs x et y dans un croquis arduino (ce qui est beaucoup plus simple) ?

dans le premier cas, il faut jouer avec la liaison I2C

dans le second cas tu fais

#define x      {2,3,4,5,6,8,2,2,3,etc.}
#define y      {4,5,4,3,4,6,2,54,etc.}

il est facile par formule ou via ta macro d'écrire en texte ce bout de programme (j'ai souvent procédé comme cela)

tu fais ensuite copier/coller et tu compiles ton croquis

Mercii pour votre réponse mais c pas très clair , si vous pouvez encore la détailler svp ,

En fait je veux lire les données de l'excel parce que ces données peuvent toujours varier , donc je veux que l'arduino prend de l'excel les valeurs et les intègre dans son programme .

je sais pas comment procéder.

Mercii pour votre aide

En fait je veux lire les données de l'excel parce que ces données peuvent toujours varier , donc je veux que l'arduino prend de l'excel les valeurs et les intègre dans son programme .

ok

D'abord, la carte arduino ne pourra pas directement lire les données d'excel, mais ce n'est pas grave car il y a toujours la possibilité d'utiliser une copie qu'excel fera dans un fichier texte par macro.

Je détaillerai les différentes possibilités après avoir fait un essai...

Je vais commencer par le plus simple, encore que j'ai poussé cette solution un peu loin quand même, de quoi se faire plaisir !

Le fichier excel suivant générera un fichier compatible arduino inclus dans le bibliothèque.

Il faut que tu indiques dans le programme VBA où se trouve ton répertoire Arduino

Option Explicit
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Const SW_SHOWNORMAL = 1

Sub enregistrer()

Dim repArduino As String
repArduino = "C:\Users\Michel\OneDrive\Documents\arduino"

test_repertoire repArduino & "\libraries\DataExcel"

' ecriture
    On Error GoTo ErreurEcriture
    Open repArduino & "\libraries\DataExcel\DataExcel.h" For Output As #1
        Print #1, max(1)
        Print #1, variable(1)
        Print #1, max(2)
        Print #1, variable(2)
    Close #1
    MsgBox "écriture terminée"

Exit Sub

ErreurEcriture:
    MsgBox Err.Description & " (" & Str(Err.Number) & ")", vbOKOnly, "Erreur écriture"
    Close #1

Exit Sub

End Sub

Function max(colonne As Integer) As String
    max = "int max" & Cells(1, colonne) & " = " & Cells(Rows.Count, colonne).End(xlUp).Row & ";"
End Function

Function variable(colonne As Integer) As String
Dim ligne As Integer
Dim max As Integer
    max = Cells(Rows.Count, colonne).End(xlUp).Row
    variable = "int " & Cells(1, colonne) & "[] = {"
    For ligne = 2 To max - 1
        variable = variable & Cells(ligne, colonne) & ","
    Next
    variable = variable & Cells(max, colonne) & "};"
End Function

Sub test_repertoire(chemin As String)
Dim fs As Object
Set fs = CreateObject("Scripting.FileSystemObject")
If fs.FolderExists(chemin) Then
Else: fs.CreateFolder chemin
End If
Set fs = Nothing
End Sub

Ensuite, tu compiles ton croquis qui fera appel à ce fichier. Voici un croquis hyper simple qui peut te servir de test via le moniteur série.

#include <DataExcel.h>

void setup()
{
  Serial.begin(9600);
  int i;
  Serial.println("x =");
  for (i = 0; i < maxx-1; i = i + 1) {
    Serial.println(x[i]);
  }
  Serial.println("y =");
  for (i = 0; i < maxy-1; i = i + 1) {
    Serial.println(y[i]);
  }
}

void loop()
{
}

Cette solution est simple mais nécessite de recompiler le croquis à chaque évolution des données (ce qui pourrait aussi s'automatiser en faisant appel à un autre logiciel ... restons dans le domaine excel et arduino).

Si ce n'est pas satisfaisant, il faut passer à une solution où le programme arduino ira chercher lui-même les informations après compilation.

249exceltoarduino.xlsm (18.37 Ko)

@hajara

Cette solution ("avant compilation du croquis") te convient-elle ou dois-je sortir une solution "après compilation du croquis" ?

Cette autre solution nécessite de communiquer avec l'Arduino; il a 2 grandes façons de le faire :

  • via la liaison série
  • via une requête http pour aller chercher les données sur un serveur (ce qui requiert un bouclier (shield) wifi ou ethernet)

@hajara

pas de nouvelles, bonnes nouvelles ?

J'expose ici le cas où les données sont envoyées après compilation du croquis via l'interface série (port COMx)

La liaison série d'excel nécessite le composant MsComm32.ocx qui n'est plus installé. Il n'est pas évident de trouver MsComm32.ocx complet et dans sa dernière version.

Une solution a été développée par

Tant qu' ajouter un composant, autant utiliser l'interface série de l'IDE Arduino et un utilitaire (absolument inoffensif, j'ai mis le code source dans le fichier texte du zip) que j'ai développé avec AutoIt

178toarduino.zip (445.93 Ko)

Un exemple de transmission structurée des données de x puis de y :

exemple de croquis arduino (là on est limite forum excel, mais comme il s'agit d'interfacer ...):

// chaine taille maxi et nombre de données
// format "<variable=N/x1,x2,...,xn>"
const byte numChars = 32;
const byte nombres = 9;

char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC;
float floatFromPC[nombres];
int nbre;

boolean newData = false;

//============

void setup() {
    Serial.begin(9600);
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,"=");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

    strtokIndx = strtok(NULL, "/"); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

  int i;
  for (i = 0; i < integerFromPC; i = i + 1) {
    strtokIndx = strtok(NULL, ",");
    floatFromPC[i] = atof(strtokIndx);     // convert this part to a float
  }

}

//============

void showParsedData() {
    Serial.print("Variable ");
    Serial.println(messageFromPC);
    Serial.print("Nombre ");
    Serial.println(integerFromPC);
    Serial.println("Data ");
  int i;
  for (i = 0; i < integerFromPC; i = i + 1) {
    Serial.println(floatFromPC[i]);
  }

}

Dernier cas ... les moteurs sont embraqués sur un robot autonome (sans fil à la patte !)

Dans ce cas, je dirais qu'il n'y a plus d'interface et la meilleure solution est

  • côté excel : envoyer par ftp les données sur un serveur
  • côté arduino : doter d'un bouclier (shield) wifi et effectuer une requête sur le serveur

Je reviens sur le sujet avec une amélioration

Le fichier excel suivant est auto-suffisant, plus d'interface

Il utilisera le moniteur série de l'IDE arduino

183piloterarduino.xlsm (20.99 Ko)
' http://www.generation-nt.com/reponses/vba-avoir-liste-fenetre-windows-ouvertes-entraide-298662.html

Private Declare Function GetWindowTextLength Lib "user32.dll" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long
Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long

Private Function EnumWindowsProc&(ByVal hwnd&, ByVal lParam&)
Dim SLength&, Buffer As String, RetVal&
SLength = GetWindowTextLength(hwnd) + 1
If SLength > 1 Then
    Buffer = Space(SLength)
    RetVal = GetWindowText(hwnd, Buffer, SLength)
    If CBool(IsWindowVisible(hwnd)) Then
        temp = Left(Buffer, SLength - 1)
        If temp Like "*| Arduino*" Then Range("arduino").Value = temp
        If temp Like "COM*" Then [COM] = temp
    End If
End If
EnumWindowsProc = 1
End Function

Sub RechercheArduinoWindows(ok As Boolean) 'ok pour éviter le lancement direct
    EnumWindows AddressOf EnumWindowsProc, 0
End Sub

Function activer(ok As Boolean)

activer = False

    Range("arduino").Value = ""
    Range("COM").Value = ""

    RechercheArduinoWindows True

    If Range("arduino").Value = "" Then
        MsgBox "Application arduino.exe non lancée ... " & vbCrLf & "tentative de lancement (attendre 10s après ok)"
        ret = Shell(Range("programme").Value, vbNormalFocus)
        Application.Wait Time + TimeSerial(0, 0, 10)
        RechercheArduinoWindows True
        If Range("arduino").Value = "" Then
            MsgBox "Impossible de lancer l'application Arduino !" & vbCrLf & "Vérifiez son emplacement."
            Exit Function
        End If
    End If

    If Range("COM").Value = "" Then
    MsgBox "Moniteur série non lancé ... " & vbCrLf & "tentative de lancement (attendre 2s après ok)"
        AppActivate Range("arduino").Value
        Application.SendKeys ("^M")
        Application.Wait Time + TimeSerial(0, 0, 2)
        RechercheArduinoWindows True
        If Range("COM").Value = "" Then
            MsgBox "Impossible de lancer le moniteur série !" & vbCrLf & "Branchez votre cate sur le port USB."
            Exit Function
        End If
    End If

activer = True

End Function

Sub envoyer()

    chaine = Range("chaine").Value
    If activer(True) Then
        AppActivate Range("COM").Value
        Application.SendKeys chaine
        Application.SendKeys ("~")
    End If

End Sub

exemple de code arduino :

// Example 3 - Receive with start- and end-markers

const byte numChars = 32;
char receivedChars[numChars];

boolean newData = false;

void setup() {
    Serial.begin(9600);
}

void loop() {
    recvWithStartEndMarkers();
    showNewData();
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print(receivedChars);
        Serial.println(" ... ok");
        newData = false;
    }
}

Bonjour

Je trouve ce fil intéressant.

J'ai eu un problème de flashage sur mon uno sinon j'aurais bien testé tout cela par curiosité ...

Je trouve ce fil intéressant.

Merci Chris pour ta remarque.

Absolument, j'ai beaucoup appris en le faisant, ce n'était pas du "tout cuit" et c'est cela aussi qui est intéressant, chercher, réfléchir, tester, réaliser. Et marier le VBA, le code Arduino et même AutoIt, un vrai plaisir.

mais j'ai l'impression qu'on a perdu le client !

Rechercher des sujets similaires à "liaison arduino"