Problème communication port serial.

Hello, je suis sur un nouveau projet: un notificateur de mails. J'en suis qu'à des phases de test, et ça commence plutôt mal...
Principe: j'utilise un scripte python qui se connecte à ma boite mail et qui vérifie si oui ou non il y a des mails non lus:

import serial, sys, feedparser
#Settings - Change these to match your account details
USERNAME="xxxxxxxx@gmail.com"
PASSWORD="**************"
PROTO="https://"
SERVER="mail.google.com"
PATH="/gmail/feed/atom"
SERIALPORT = "COM3" # Change this to your serial port!
# Set up serial port
try:
	ser = serial.Serial(SERIALPORT, 9600)
except serial.SerialException:
	print "no device connected - exiting"
	sys.exit()

newmails = int(feedparser.parse(PROTO + USERNAME + ":" + PASSWORD + "@" + SERVER + PATH)["feed"]["fullcount"])
   
# Output data to serial port
if newmails > 0: 
	ser.write("m")
	print "some mail"
else: 
	ser.write("n")
	print "no mail" 
#print data to terminal


# Close serial port
ser.close()

Ce dernier envoie le résultat au port COM3 où est connecté mon arduino (je suppose que c'est le COM3 puisque indiqué dans le logiciel arduino). Ce code fonctionne, donc le problème ne vient surement pas de là, enfin, il détecte bien si oui ou non j'ai des mails.

Ensuite, l'arduino reçoit l'information:

// led wired + to pin 12, resistor to positive +5v

int outPin = 12; // Output connected to digital pin 12
int mail = LOW; // Is there new mail?
int val; // Value read from the serial port

void setup()
{
 pinMode(outPin, OUTPUT); // sets the digital pin as output
 Serial.begin(9600);
 Serial.flush();
 mail = HIGH; // start off with lights out
}

void loop()
{
 // Read from serial port 
 if (Serial.available() > 0)
 {
   val = Serial.read();
   

   if (val == 110) // n = 110 in dec
   {
     mail = HIGH;  // HIGH is off because led is connected to +5v on the other side     
   }

   else if (val == 109) //109 = m in dec
   {
     mail = LOW; // LOW is on because led is connected to +5v on the other side
   }
 }

 // Set the status of the output pin
 digitalWrite(outPin, mail); 
}

Sauf que là... bin, ça marche pas ^^. Ma led tressaute un millième de seconde, mais pas moyen de la laisser allumée quand j'ai un nouveau mail... J'ai testé en remplaçant "m" et "n" par "42" et "43" mais même chose...

Une idée ?

Yep!

Plus simple et plus lisible :

 // Read from serial port 
 if (Serial.available()) {
   val = Serial.read();

   if (val == 'n') {
     ...
   }
   else if (val == 'm') {
     ...
   }
 }

@+

Zoroastre.

Yop

if newmails > 0: 
	ser.write("m")
	print "some mail"
else: 
	ser.write("n")
	print "no mail"

Je dirais inverse m et n, si dessus tu dis 'm' si newmails > 0 mais en bas tu mets ta sortie à LOW si 'm' ...

// HIGH is off because led is connected to +5v on the other side

C'est un code que tu as repris vu l'inversion, ou t'on montage est identique ?

   if (val == 110) // n = 110 in dec
   {
     mail = HIGH;  
   }

   else if (val == 109) //109 = m in dec
   {
     mail = LOW; 
   }
if (Serial.available() > 0)
 {
   val = Serial.read();
   
   if (val == 'm') // n = 110 in dec
   {
     mail = HIGH;  // HIGH is off because led is connected to +5v on the other side     
   }

   else if (val == 'n') //109 = m in dec
   {
     mail = LOW; // LOW is on because led is connected to +5v on the other side
   }
 }

tu ne mettrais pas directement ton changement d'état dans ta condition ( available() ) de réception serie ?
Comme tu ne change l’état qu'a la réception de données ?
! loop() = boucle infinie.
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Loop

if (Serial.available() > 0)
 {
  .
  .
  .
  digitalWrite(outPin, mail); 
 }

plus variable 'val' et 'mail' inutile en global, sauf si tu dois encore t'en servie autre part ?

entre () juste pour information , ceci:

if (Serial.available() > 0)

ou celà:

if (Serial.available())

revient au même, toute valeur différente de 0 est considérer comme vraie, même les nombres négatif.

Petite leçons pour t'aider :wink: :

int outPin = 12; // Output connected to digital pin 12
int mail = LOW; // Is there new mail?
int val; // Value read from the serial port

Couramment constaté chez les débutants, l'utilisation inutile du type int (2 octet de 0 à 65535 non-signé) pour des variable qui ne dépasseront jamais 1 octet (valeur de 0 à 255 non-signé) ou même un bit pour 'mail' qui n'aura jamais que deux valeur (0 ou 1: voir les booléens), enfin de ce côté là 1octet obligatoire même si qu'un seul bit d'utilisé.

http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Int
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Boolean
(le type char, byte, boolen revient au même, 1 octet il rentre tous l'un dans l'autre)

Pour les "variables" qui ne changeront jamais comme pour outPin tu peux utiliser l'instruction #define tu économisera justement une "variable".
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Define

Là où dans pyton le typage (dynamique pour celui ci) parait désuet sur pc ici il l'est moin, comme je l'avais déjà dit une fois pour php ce n'est pas l'idéal pour les débutants.
:wink:

L'inversion m et n ne change rien, et en effet c'est un code que j'ai récupéré, mais j'ai voulu modifier m et n par 42 et 43 pour tester sauf que je me suis planté. Quoi qu'il arrive, cette led ne veut pas s'allumer, j'en conclut que la carte ne reçoit pas la bonne valeur...

[edit] Quand je la met en mode allumée de base, et que je met mail = HIGH dans les deux conditions, la led reste allumée tout le temps. Donc cela veut dire qu'aucune des deux conditions n'est respectée, que j'ai un mail ou non. Je vois pas comment résoudre ça...

Yep!

Il faudrait déjà garantir que tu envoies bien quelque chose !!!

if (Serial.available()) {
  val = Serial.read();
  delay(2);
  Serial.print("value: "); Serial.println(val);

}

Et tu affiches le moniteur serie de l'IDE arduino.

EDIT1 : Ce qui m'embête dans ton script python c'est cette partie, tu pourrais me l'expliquer ???

feedparser.parse(PROTO + USERNAME + ":" + PASSWORD + "@" + SERVER + PATH)["feed"]["fullcount"]

["feed"]["fullcount"] ???

@+

Zoroastre.

ça l'affiche où le résultat ? sur la "console" du logiciel arduino ?
[EDIT] Le code n'étant pas de moi, je ne peut rien en dire, car je ne suis qu'un débutant en python. Je pense tout simplement que cela permet une connection à mon compte gmail et un test sur une variable qui indique la présence de mails. En tout cas, cette partie marche, c'est sur ! Avec print"some mails" et print"no mails", pas d'erreurs possibles, à chaque fois ça correspond à la réalité.

Yep!

Arduino->Tools->Serial Monitor

Et tu choisis le bon baud...(9600)

Tu peux également essayer d'envoyer tes commandes dans le moniteur.

@+

Zoroastre.

Héhé, c'est con, mais il semblerait que le moniteur entre en conflit avec le script python: quand le moniteur est lancé, le script me donne une erreur qui correspond à "périphérique débranché", du coup, il envoi rien à l'arduino =/

Yep!

C'est normal, faut lancer le script python aprés.

@+

Zoroastre.

ça change rien: je lance le moniteur, j'ouvre le script, je le lance, et j'ai:

no device connected - exiting
Traceback (most recent call last):
  File "C:\Users\Utilisateur\Documents\Arduino\Arduino_Gmail_Checker\Arduino_Gmail_Checker\check-gmail.py", line 14, in <module>
    sys.exit()
SystemExit

Y'a pas une fonction à envoyer avec le moniteur pour récupérer "val" de la mémoire de l'arduino après avoir lancé le script ? enfin, celle ci ne devrait pas avoir changé non ?

[edit] quand j'envoie "m" avec le moniteur, la led s'éteint ! Par contre, chose peut être bizarre, la led ne cligne pas quand elle reçoit l'info, contrairement à quand je le fais avec le script python (elle s'éteint moins d'une demi seconde, puis se rallume).

Yep!

Ce que je te propose est de d'abord valider ton sketch

// led wired + to pin 12, resistor to positive +5v

#define outPin 12

int val;

void setup()
{
 pinMode(outPin, OUTPUT); // sets the digital pin as output
 Serial.begin(9600);
 Serial.flush();
}

void loop()
{
 // Read from serial port 
 if (Serial.available()) {
   val = Serial.read();
   delay(2);
   Serial.println(val);

   if (val == 'n')
   {
     digitalWrite(outPin, HIGH);
   }

   else if (val == 'm')
   {
     digitalWrite(outPin, LOW);
   }
 }

  
}

Et tu envoies des m et des n par le moniteur arduino.

On verra aprés ton script python.

@+

Zoroastre.

J'ai fait un édit plus haut.
Avec ton code, ça ne fonctionne pas (via moniteur), la led reste éteinte tout le temps, tandis qu'avec le code d'avant, ça fonctionnait. J'ai remplacé 'm' et 'n' par 109et 110 mais idem, fonctionne pas. Donc on reste sur ce code pour l'arduino:

// led wired + to pin 12, resistor to positive +5v

int outPin = 11; // Output connected to digital pin 12
int mail = LOW; // Is there new mail?
int val; // Value read from the serial port

void setup()
{
 pinMode(outPin, OUTPUT); // sets the digital pin as output
 Serial.begin(9600);
 Serial.flush();
 mail = LOW; // start off with lights out
}

void loop()
{
 // Read from serial port 
 if (Serial.available())
 {
   val = Serial.read();
   delay(3000);
   Serial.print("value: "); Serial.println(val);

   if (val == 110){// n = 110 in dec
     mail = HIGH;  // HIGH is off because led is connected to +5v on the other side     
   }

   else if (val == 109){ //109 = m in dec
     mail = LOW; // LOW is on because led is connected to +5v on the other side
   }
 }

 // Set the status of the output pin
 digitalWrite(outPin, mail); 
}

Yep!

Ben mon code fonctionne man :fearful:

Je viens de le tester en direct live...

// led wired + to pin 12, resistor to positive +5v

#define outPin 12

int val;

void setup()
{
 pinMode(outPin, OUTPUT); // sets the digital pin as output
 Serial.begin(9600);
 Serial.flush();
}

void loop()
{
 // Read from serial port 
 if (Serial.available()) {
   val = Serial.read();
   delay(2);
   Serial.println(val);

   if (val == 'n')
   {
     digitalWrite(outPin, HIGH);
   }

   else if (val == 'm')
   {
     digitalWrite(outPin, LOW);
   }
 }

  
}

Ressayes ton ancien code !!!

@+

Zoroastre.

Je t'assure qu'il fonctionne pas chez moi ^^. Bref, j'ai donc reprit mon ancien code, j'ai rajouté tes deux lignes, et j'ai assu rajouté des lignes dans le script python pour qu'il récupère et affiche ce qu'envoie arduino, bilan, ça bug pas mal (I don't know why), le script plante une fois sur deux, mais je reçois quand même qqch:

no mail
value: 110

Le code python:

import serial, sys, feedparser
#Settings - Change these to match your account details
USERNAME="xxxxxx@gmail.com"
PASSWORD="********"
PROTO="https://"
SERVER="mail.google.com"
PATH="/gmail/feed/atom"
SERIALPORT = "COM3" # Change this to your serial port!
# Set up serial port
try:
	ser = serial.Serial(SERIALPORT, 9600)
except serial.SerialException:
	print "no device connected - exiting"
	sys.exit()

newmails = int(feedparser.parse(PROTO + USERNAME + ":" + PASSWORD + "@" + SERVER + PATH)["feed"]["fullcount"])
   
# Output data to serial port
if newmails > 0: 
	ser.write('m')
	val = ser.readline()
	print "some mail"
	print(val)
else: 
	ser.write('n')
	val = ser.readline()
	print "no mail"	
	print(val)
#print data to terminal


# Close serial port
ser.close()

J'ai rajouté "val = ser.readline()" et "print(val)", c'est tout. Et va savoir pourquoi, le programme plante en fait toujours à la seconde fois: je le lance, ça marche une fois, je le relance, et il plante (je le lance depuis idle si tu connais).

Bref, c'est bizarre, arduino recevrait bien la bonne valeur, mais ça ne fonctionne quand même pas tandis qu'avec le moniteur si... =/

[EDIT] De plus en plus bizarre: si je passe par la ligne de commande python, et que je refais toutes les étapes une par une à la main (création et ouverture du port, puis envoi de 'n' ou 'm'), ça marche ! J'ai donc modifier le script python pour mettre exactement les mêmes commandes que j'ai utilisé, mais ça ne fonctionne pas.

Ma console python:

import serial
ser = serial.Serial()
ser.bauderate = 9600
ser.port = 2
ser.open()
ser.write('n')

Et là, la led s'éteint, et reste éteinte ! Du coup, je modifie mon script python comme suit:

import serial, sys, feedparser
#Settings - Change these to match your account details
USERNAME="xxxxxx@gmail.com"
PASSWORD="*******"
PROTO="https://"
SERVER="mail.google.com"
PATH="/gmail/feed/atom"
SERIALPORT = 2 # Change this to your serial port!
# Set up serial port
try:
	ser = serial.Serial()
	ser.baudrate = 9600
	ser.port = 2
	print ser
	ser.open()
	print ser.isOpen()
except serial.SerialException:
	print "no device connected - exiting"
	sys.exit()

newmails = int(feedparser.parse(PROTO + USERNAME + ":" + PASSWORD + "@" + SERVER + PATH)["feed"]["fullcount"])
   
# Output data to serial port
if newmails > 0: 
	ser.write('m')
	
	print "some mail"	
else: 
	ser.write('n')
	
	print "no mail"		
#print data to terminal


# Close serial port
ser.close()

Mais que dalle U_u, ça fonctionne pas !!!!! :0 :0 :0

Yep!

Pour ma part, j'utilise mon sketch précedent et j'ai testé l'envoie de m/n par le serial monitor et également par la console de idle. Impec chez moi.

IDLE 2.6.6

import serial
ser = serial.Serial('/dev/ttyUSB0',9600)
ser.write('m')
ser.write('n')
ser.write('m')
ser.write('n')
ser.write('m')
ser.write('n')
ser.write('m')

Y'a un truc qui cloche déjà avec ton sketch. Il doit fonctionner à tous les coups.

@+

Zoroastre.

Yep!

Fait aussi un print de newmails pour voir ce qu'il affiche...

@+

Zoroastre.

up (edit du dessus)

Yep!

Tu peux faire un print dans ton script python de la variable : newmails

Je voudrais voir ce qu'elle donne, j'ai pas vu au dessus...

@+

Zoroastre.

Si ça te dérange pas, je peux te mp mon adresse msn pour discuter plus efficacement ? Je posterai la solution bien sûr si on trouve ^^

Yep!

Heuuuu!!! msn...Faut que je regarde si j'ai encore un compte quelque part :fearful:

Je t'envoie mon mail par mp

@+

Zoroastre.