Go Down

Topic: Librairie Time et serial call/response (Read 1 time) previous topic - next topic

zoroastre

Jun 22, 2011, 12:54 am Last Edit: Jun 22, 2011, 01:01 am by zoroastre Reason: 1
Yep!

Bon ! Depuis un an d'absence je mets mes librairies à jour et pourtant...

Quelqu'un a-t'il déjà essayer d'implémenter dans son code la librairie Time et une transmission de données via un classique serial call/response ???

Code: [Select]
if(Serial.available())
   {
    int inByte = Serial.read();
    switch (inByte) {
    case 'a':
       processSyncMessage();
       Serial.println("READ : a");
    case 'b':
       Serial.println("READ : b");
........................

Un de mes nombreux essais malheureux...les données transitent, mais l'horloge ne se met pas à jour...

En fait, je tente de communiquer un max de données par l'intermédiaire du pc, et en outre l'horloge ainsi qu'un update de certaines variables via un interface web/python. J'utilise donc des bytes pour initier les differentes transmissions. Eh ben que nenni ! La bibliothèque Time me fout tout en l'air, rien de passe, çà bloque ou défile indefinément.
Je vous laisse volontier faire les tests et me démontrer le contraire. J'ai essayé les if, les switch/case,etc.
Indépendement, les deux fonctionnent. Ensembles, c'est le foutoirs  :smiley-eek:

Je pense revenir à la bibliothèque DateTime qui me semble plus propre et plus adequat avec ce que je cherche à faire, voire à construire ma propre bibliothèque...J'ai encore de nombeux essais à faire, mais là je ne vois pas de solutions dans l'instant...

Alors comment avoir une communication efficace entre l'arduino et le port série/pc avec comme prérogative une horloge temps réel (serial elle aussi) ???

Me parler pas d'un DS13** ou autre. Tout autre solution alternative m'interesse ;)

Hum! Je pourrais tout passer du côté pc avec python...

@+

Zoroastre.

PS : Là j'en ai marre de chercher. Je bloque sérieusement. Je suis une pu$**n de buse de me$d*.
Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message ;)

B@tto

Salut,

La librairie time te sert à faire quoi exactement ? Parce que les éventuelles solutions de remplacement vont dépendre de ce que tu as besoin. A la volée il y a effectivement le DS1307, tu peux aussi envoyer l'heure à partir du PC, utiliser la fonction millis() ...
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

zoroastre

#2
Jun 22, 2011, 04:19 pm Last Edit: Jun 22, 2011, 04:47 pm by zoroastre Reason: 1
Yep!

Merci pour ton interêt B@tto ;)

J'essaye effectivement de transmettre l'heure à l'arduino, mais je voudrais en plus pouvoir envoyer des données par l'intermédiaire d'une interface python. Pour moi, l'idéal serait de tout gérer côté pc.

Je commence donc à avoir des resultats. La commande write (python) semble réclamer un release aprés son execution. Pourtant, j'ai des résultats totalement aléatoires et incoherants...J'ai testé les carriage return, les sauts de ligne, différents delais...

Les scripts d'essai :
Code: [Select]
#include <Time.h>

#define TIME_MSG_LEN  11
#define TIME_HEADER  'T'
#define TIME_REQUEST  7

int inByte;

void setup()
{
// connexion usb
Serial.begin(9600);
Serial.println("MSG : Waiting for sync message");
setSyncProvider(requestSync);
delay(100);
Serial.println("MSG : setup complete");
}

void loop()
{
 if (Serial.available()>0) {
 int inByte = Serial.read();
 switch (inByte) {
   case '5' :
     Serial.println("READ : 5");
   case '4' :
     Serial.println("READ : 4");
     delay(10);
     Serial.print(TIME_REQUEST, BYTE);
     processSyncMessage();
 }
}
   delay(2500);
   Serial.println("DBG : START TRANSMISSION");
   delay(2500);
   Serial.println("a");
   delay(2500);
   Serial.println("1");
   delay(2500);
   Serial.println("SYN");
   delay(2500);
   Serial.print(hour());
   Serial.print(":");
   Serial.println(minute());
   Serial.println("END OF TRANSMISSION");
   delay(2500);
}

void processSyncMessage() {
 // if time sync available from serial port, update time and return true
 while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
   char c = Serial.read() ;
   Serial.print(c);  
   if( c == TIME_HEADER ) {      
     time_t pctime = 0;
     for(int i=0; i < TIME_MSG_LEN -1; i++){  
       c = Serial.read();          
       if( c >= '0' && c <= '9'){  
         pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
       }
     }  
     setTime(pctime);   // Sync Arduino clock to the time received on the serial port
   }  
 }
}

time_t requestSync()
{
 Serial.print(TIME_REQUEST,BYTE);  
 return 0; // the time will be sent later in response to serial mesg
}


Code: [Select]
import serial, time

ser = serial.Serial('/dev/ttyUSB0',9600)

def update_time():
   time.sleep(0.1)
   tic = time.time() - time.timezone + time.daylight*3600
   tics = 'T' + str(tic)[0:10]
   ser.write(tics)

while 1:
   data = ser.readline()
   if data[0:1] == '1' :
       print "RECEIVED - 1"
   if data[0:1] == 'a' :
       print "RECEIVED - a"
   if data[0:1] == '\7' :
       update_time()
       time.sleep(0.2)
       print "TIME UPDATED"
   if data[0:3] == 'END' :
       time.sleep(0.1)
       ser.write('5')
       time.sleep(0.1)
   if data[0:3] == 'SYN' :
       print "RECEIVED SYN"
       ser.write('4')
       time.sleep(0.1)
   print data


J'aimerais éviter les pertes de donner et stabiliser tout cà. L'interface python que je développe est multithread avec une partie pour enregistrer les logs transmises par l'arduino et une autre permettant d'envoyer des données vers l'arduino. J'envisage d'autres solutions, mais à vrai dire, je reprends les choses depuis le début.

Je n'ai pas de problème pour enregistrer les data, mais je manque de précision du pc vers l'arduino.

Code: [Select]
READ : 5

READ : 4

TIME UPDATED
DBG : START TRANSMISSION

RECEIVED - a
a

RECEIVED - 1
1

RECEIVED SYN
SYN

RECEIVED - 1
16:4

END OF TRANSMISSION

DBG : START TRANSMISSION

MSG : Waiting for sync message

TIME UPDATED
MSG : setup complete

DBG : START TRANSMISSION

RECEIVED - a
a

RECEIVED - 1
1

RECEIVED SYN
SYN

TIME UPDATED
0:0

END OF TRANSMISSION


Aprés un reboot de l'arduino par exemple, la mise à jour de l'horloge ne se fait plus...de plus certaines info ne semblent plus être correctement gérées.
J'aimerais avoir des précisions sur comment appréhender correctement la com du pc vers l'arduino et sur le buffer ???

@+

Zoroastre.
Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message ;)

zoroastre

#3
Jun 25, 2011, 09:43 pm Last Edit: Jun 25, 2011, 10:56 pm by zoroastre Reason: 1
Yep!

Bon, j'ai résolu mon problème initial. J'arrive enfin à synchro l'heure entre le pc et l'arduino tout en gérant une structure de communication sériel. J'ai tout simplement incorporé la mise à jour de l'heure à mon message de communication.
Pour préciser mes desideratas, je voudrais incorporer à mon projet, la possibilité de modifier les variables ou les modes de fonctionnement soit par l'intermédiaire de script pc (python) soit par un afficheur glcd tactile (S1D13700).
Les données, ainsi qu'un système de log, seront écrites dans des fichiers afin de garantir un aspect statique et dynamique à la fois, un peu à la manière unix.

Actuellement, j'envoie les données du pc vers l'arduino dans un tableau 2D. La première dimension sert de donnée d'entrée, la seconde dimension distribuera les variables à l'arduino.

Le script :
Code: [Select]

/*
Simple Message system arduino/serial pc
1 - Clock update
2 - Send Log
3 - Retrieve data
The goal is to have a synchronized table with index

1 - {START BIT}
2 - {IsUpdate 0/1}
# BEGIN OF DATA
3 - {MODE AUTO/AWAY/VACANCY/OFF}
4 - {A FLOAT}
5 - {AN INT }
6 - {A CHAR}
# END OF DATA
7 - {STOP BIT}

EXAMPLE MSG :
T1309023435|15.25Z
FORMAT
T1234567890 | 1 | 2345 | 68

*/

#include <string.h>
#include <stdlib.h>

#include <OneWire.h>
#include <DallasTemperature.h>

#include <Time.h>

#define ONE_WIRE_BUS 3
#define TEMPERATURE_PRECISION 10

#define TIME_MSG_LEN  11
#define DATA_HEADER  'T'
#define DATA_REQUEST  7

#include <OneWire.h>
#include <DallasTemperature.h>

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

uint8_t indoor[8] = {0x28, 0xFC, 0x97, 0x56, 0x2, 0x0, 0x0, 0x69};

float tempC0;
int _minute, last_minute;

// index for server message array
int  serveIn;
char serveInString[1][25];
int  serveInIndx  = 0;
int  serveOutIndx = 0;

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

void loop() {
 
processSyncMsg();
 
delay(2000);

//request time if needed
if(timeStatus() == timeNotSet)
 {
     checkTime();
 }

// set time vars
int _hour = (hour());
int _minute = (minute());
int current_time = (_hour*60) + _minute;

delay(2000);

// print log every minute
if (_minute != last_minute)
{
 sensors.requestTemperatures();
 tempC0 = sensors.getTempC(indoor);
 last_minute = _minute;
 Serial.print(_hour);
 Serial.print(":");
 Serial.print(_minute);
 Serial.print("|");
 Serial.print(current_time);
 Serial.print("|");
 Serial.print(tempC0);
 Serial.println("°C");
}

delay(1000);

}

void readMessageFromServer() {
   int sb;  
   if(Serial.available()) {
      Serial.print("reading Server String: ");     //optional confirmation
      while (Serial.available()){
         sb = Serial.read();
         serveInString[0][serveInIndx] = sb;
         serveInIndx++;
         Serial.write(sb);                        //optional confirmation
      }
      Serial.println();
   }  
}

void printMessageFromServer() {
 if( serveInString > 0) {
   Serial.print("Arduino memorized MESSAGE: ");
   if ((serveInString[0][0] == DATA_HEADER)) {
      for(serveInIndx=0; serveOutIndx < 15; serveOutIndx++) {
         Serial.print(serveInString[0][serveOutIndx]); }
   }
 }
     // reset array
     serveOutIndx = 0;
     serveInIndx  = 0;
     //Serial.println();
}

void processSyncMsg() {
 readMessageFromServer();
 Serial.print(DATA_REQUEST, BYTE);
 printMessageFromServer();
}

boolean checkMsg() {
 if (serveInString[0][0] == serveInString[1][0]) {
   return true; }
 else {
   return false; }
}


void checkTime() {
 if( serveInString > 0) {
   Serial.print("Arduino memorized TIME: ");
   if ((serveInString[0][0] == DATA_HEADER)) {
      time_t pctime = 0;    
     //loop through all bytes in the array and print them out
     for(serveOutIndx=0; serveOutIndx < TIME_MSG_LEN; serveOutIndx++) {
       Serial.print(serveInString[0][serveOutIndx]);    //print out the byte at the specified index          
       if( int(serveInString[0][serveOutIndx]) >= '0' && int(serveInString[0][serveOutIndx]) <= '9'){  
         pctime = (10 * pctime) + (int(serveInString[0][serveOutIndx]) - '0') ; // convert digits to a number    
       }
     }
     setTime(pctime);   // Sync Arduino clock to the time received on the serial port

         }
   }
   // reset array
     serveOutIndx = 0;
     serveInIndx  = 0;
}



C'est trés artisanal comme vous pouvez le constater.
Il me reste à faire :
 - Inclure un séparateur entre les données de la trame <-- Cà c'est ok
 - détecter automatiquement la taille des données        <-- J'y reflechis.
 - Pouvoir ne modifier qu'un index de la table                 <-- peut-être une table 3D + separateur [index:val]
 - ...

Je découvre complètement cet aspect de la programmation et cherche dans plusieurs directions en même temps. Je sais qu'il existe des librairies ayant les mêmes optiques(firmata, pyduino, simple messenger), mais aucunes ne me convenaient, trop rigides, pas adaptés à mes besoins.(C'est tellement mieux quand c'est DIY ;) )

Le script python (simplicisme) :
Code: [Select]

import serial, time

ser = serial.Serial('/dev/ttyUSB0',9600, timeout=0.2)
logs = []

def send_msg():
   tic = time.time() - time.timezone + time.daylight*3600
   tics = 'T' + str(tic)[0:10]
   ser.write(tics + '|' + '15.25Z'+'\r')

def retrieve_log() :
   pass
   
while 1:
   data = ser.readline()
   if data:
       if data[0:1] == '\7' :
           send_msg()
       print data


J'arrive pour finir à convertir les caratères en int ou en float sous l'arduino, donc pas de souci de se côté là.


J'attends vos commentaires/recommandations/critiques avec impatience ;)

@+

Zoroastre.
Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message ;)

Go Up