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
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 SubEnsuite, 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.
@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
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
' 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 Subexemple 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
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 !