Question

Bonjour! Récemment, j'acheté une carte Arduino pour faire sorte de « contrôle de la lumière » dans ma chambre. Voici le code du firmware que j'ai écrit:

int control = 0;
int pin = 0;

void setup()
{
  Serial.begin(9600);
  for(pin = 0; pin <= 13; pin++) pinMode(pin, OUTPUT);
}

void loop()
{
  control = Serial.read();
  if (control > 0 && control <= 13) digitalWrite(control, HIGH);
  if (control < 256 && control >= (256-13)) digitalWrite((256-control), LOW);
}

Après cela, je pyserial d'interpréteur Python pour contrôler les broches, et tout fonctionnait très bien. Voici un morceau de sortie interprète:

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyUSB0', 9600)
>>> ser.write(chr(12))
>>> # The light turned on here
... 
>>> ser.write(chr(256-12))
>>> # The light turned off here
...

Alors j'ai décidé d'écrire un simple script Python pour faire la même chose:

#!/usr/bin/env python

import serial
import time

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

ser.write(chr(12))
time.sleep(1)
ser.write(chr(256-12))

Mais ça ne marche pas du tout! Les spectacles Arduino que quelque chose a été reçu pendant le temps que je lancé le script, mais rien ne se passe. Voici un morceau de sortie strace pour le script:

open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK) = 4
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_START or TCSETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
write(4, "\f", 1)                       = 1
close(4)                                = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f45cf4c88f0}, {0x4d9820, [], SA_RESTORER, 0x7f45cf4c88f0}, 8) = 0
exit_group(0)                           = ?

Il semble que tout devrait être bon, donc je ne sais pas ce que le problème peut être. Je vous serais reconnaissant toute aide, merci beaucoup à l'avance!

PS Quand je lance le programme dans l'APB, tout fonctionne bien. A Heisenbug.

Mise à jour: J'ai fait l'envoi du contrôleur-moi les données qu'il recevait et il semble que ce ne reçoit rien quand je suis en cours d'exécution du script, mais reçoit tout quand j'envoie les données de l'interprète. Le code du firmware ressemble maintenant à ceci:

int control = 0;
int pin = 0;

void setup()
{
  Serial.begin(9600);
  for(pin = 0; pin <= 13; pin++) pinMode(pin, OUTPUT);
}

void loop()
{
  if (Serial.available() > 0)
  {
    control = Serial.read();
    if (control <= 13) digitalWrite(control, HIGH);
    if (control < 256 && control >= (256-13)) digitalWrite((256-control), LOW);
    Serial.println(control);
  }
}
Était-ce utile?

La solution

Je pense qu'il est probablement une condition de course entre le moment où le port série est ouvert et lorsque les données sont envoyées. Je serais probablement coller un sommeil entre l'ouverture et les appels d'écriture.

Sinon, au lieu d'utiliser cette bibliothèque « série », vous pourriez vouloir simplement ouvrir et écrire directement sur l'appareil, peut-être qu'il fait quelque chose de drôle (voir la double ouverte mentionné dans d'autres messages)

Autres conseils

Je suppose qu'il a quelque chose à l'environnement.

import os
print os.environ['PS1']

A partir d'un script qui ne sera pas réglé. (Et peut-être aussi autre chose.)

TTY de tamponnera différemment selon qu'ils pensent ou non le terminal est interactif. Cela devrait être la seule différence entre la façon dont vos deux méthodes fonctionnent. A applications de lot décider de cela ou non PS1 (votre invite du terminal) est réglé. Si vous définissez cela dans votre environnement manuellement peut commencer à se comporter de la même manière comme il le fait de manière interactive.

En outre, je qualifierais l'appel la commande affleurant pyserial manuellement dans votre script. (Et ce serait la meilleure façon de le faire. Au lieu de se faisant passer pour une borne interactive.)

votre sortie strace montre qu'il ouvre le port série lecture / écriture deux fois . La deuxième fois, il écrit que le chr (12), ferme le fichier. Je n'ai pas assez d'informations pour résoudre le problème pour vous, mais peut-être cela aide? ou vous avez déjà figurez cela?

Pouvez-vous revérifier si la réinitialisation Arduino lorsque vous ouvrez la connexion série? Dans le cas où il ne réinitialise les premiers octets de série que vous envoyez seront reçus par le bootloader et non par votre code. Le bootloader pourrait alors supposer que vous voulez programmer le contrôleur et attendre d'autres commandes et / ou des données.

Le comportement exact du bootloader dépend de votre Arduino spécifique.

Afin de tester cette écriture d'un petit croquis clignote LED 13 et voir si l'initialisation de votre script Python affecte le clignotement. Si oui il y a un bootloader.

Pour résoudre ce problème, il existe plusieurs solutions possibles:

1) faire en sorte qu'il n'y a pas de remise à zéro causé par l'initialisation de l'interface série. 1a) faire sur le côté Python 1b) faire sur le côté Arduino   1b solution matérielle) déconnecter les traces incriminés sur la carte   solution logiciel 1b) se débarrasser du bootloader

2) ne pas envoyer des données alors que le bootloader fait son travail.

La solution la plus simple est (2) ma solution est de se débarrasser preferred du bootloader. Toutefois, dans ce cas, vous avez besoin d'un programmateur de système (ce qui est une bonne idée de toute façon).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top