Pages: [1] 2 3   Go Down
Author Topic: Strano comportamento seriale  (Read 1768 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vi descrivo il mio problema con la seriale, nella speranza che a qualcuno sia già capitato e che mi possa aiutare.

Ho il codice PHP che tramite la php.serial.class manda una stringa alla seriale e riceve una risposta.
Ecco il codice PHP
Code:
<?php
  
include "php_serial.class.php";
  
$serial = new phpSerial;
  
$serial->deviceSet("/dev/ttyACM0");
  
$serial->confBaudRate(9600);
  
$serial->deviceOpen();
  
$serial->sendMessage("b1");
  
sleep(1);
  
$read $serial->readPort();
  
$array explode(";",$read);
  
$SP_PH $array[0];
  
$SP_TE $array[1];
  
$serial->deviceClose();
?>


Il codice funziona perfettamente, tranne la prima volta che lo eseguo dopo un riavvio. La prima volta non mi arriva nessuna risposta. Sembra quasi che la seriale debba essere "svegliata".
Per svegliarla uso il seguente codice python (bottarissposta.py):
Code:
import serial

arduino=serial.Serial('/dev/ttyACM0')

arduino.write('b1')
print arduino.readline()

Eseguendo questo codice, sempre la prima volta dopo un riavvio, capita che alla prima esecuzione si "pianta" e devo interrompere con un ctrl z e rieseguendolo subito dopo tutto funziona correttamente fino al riavvio successivo, compreso il codice php.
Ecco cosa succede quanddo eseguo bottarisposta.py
Code:
root@raspberrypi:/var/www/controlpes# python bottarisposta.py
^Z
[1]+  Stopped                 python bottarisposta.py
root@raspberrypi:/var/www/controlpes# python bottarisposta.py
1202;3.3

root@raspberrypi:/var/www/controlpes#

Avete qualche idea?


Logged

0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Penso che il problema risieda nel fatto che in realta dialoghi con il bootloader.
Per usare la seriale arduino, quando da pc la apri va giù la linea reset connessa al DTR, subito dopo si può dialogare con il bootloader, se questo non
riconosce il dato inviatogli come un comando avvia il programma nella sezione utente della flash.

Per cui metti un delay dopo aver aperto la porta di almeno un secondo e riprova solo con php o solo con python. Di php non sono esperto, ma mi sembra entrambe i programmi facciano la stessa cosa.

Nota che inviando una sequenza giusta di comandi arduino risponde, dicendo più meno chi è, cioè se monta un 328, o altro. Tempo addietro ne ne è parlato qui, anche con astrobeed e in quel post c'è anche del codice python che ho scritto io. Prova a cercare post miei e di astrobeed ecc, mi pare io avessi chiesto come funziona in merito ad un programma che stavo scrivendo. Davvero è passato tanto tempo e un rifrescata a quelle info male non fa di certo, il bello sarebbe trovare quei post.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sei un grande, grazie 1000.
Mettendo una pausa di un paio di secondi funziona perfettamente.
Logged

0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sei un grande, grazie 1000.
Mettendo una pausa di un paio di secondi funziona perfettamente.

Non ringraziarmi, ti voglio vedere qui sul forum fare quello che ho appena fatto io con te. smiley-wink

Ciao.

Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Magari, ho appena cominciato e per adesso mi devo fare un tot di esperienza;
credevo fosse più semplice...

Adesso per esempio ho un altro problema che mi sta facendo diventare matto...

Da php invio una stringa sulla seriale; arduino la riceve e mi deve scrivere dei valori dentro alla Eprom.
Se tengo aperto il serial monitor da Arduino IDE mentre mando la stringa sulla seriale tutto ok, invece se chiudo il serial monitor non mi scrive i valori sulla Eprom.
Cosa potrà mai fare il serial monitor aperto per fare la differenza?
« Last Edit: March 22, 2013, 10:34:35 am by pespes » Logged

0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ogni volta che apri e chiudi il serial monitor Arduino riceve un reset, questo lo hai verificato tu con il tuo codice, quindi non usare il serial monitor, ma usa python o php se ti trovi più a tuo aggio, e non chiudere la seriale, invia i dati e mettiti in ascolto e ciò che arriva lo stampi.

Se vuoi disabilitare l'autoreset cerca nel forum, cerca l'utente Menniti e la sua guida.

Inizia da qui per l'autoreset http://arduino.cc/forum/index.php/topic,155190.0.html

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Purtroppo non è questo...
Ho provato a togliere il "$serial->deviceClose();" ma purtroppo non funziona. Ci deve essere qualcos'altro.
Il motivo per cui ho aperto il serial monitor è che stavo cercando di capire come mai non avviene la scrittura sulla Eprom e da li mi sono accorto che con il monitor aperto il problema non si presenta.
Devo però riuscire a farlo andare solo con PHP.
Logged

0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Trovato il post di cui parlavo, però leggilo tutto da l'inizio: http://arduino.cc/forum/index.php/topic,60774.msg439414.html#msg439414

Non ho ben capito con quale sequenza apri il device file, e il serial monitor, io ora penso che il device aperto da un programma e poi riaperto da un'altro programma dovrebbe dare come errore Busy o lock o simile.

Comuque, se la sequenza da php è apri device invii chiudi, e poi apri il serial monitor arduino viene resettato.

Posta il codice che usi per scrivere in eeprom, vediamo perchè non funge.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dopo svariati tentativi ci sono arrivato (spero!!!).
Dalla pagina setpoint.php faccio immettere all'utente due valori: SP_PH e SP_TE.
Li passo a salvataggioSP.php che a sua volta li da a Arduino tramite seriale.
Ecco il codice di salvataggioSP.php:
Code:
<?php
  $dainviare 
"a;".$_POST['SP_PH'].";".$_POST['SP_TE'];
  include 
"php_serial.class.php";
  
$serial = new phpSerial;
  
$serial->deviceSet("/dev/ttyACM0");
  
$serial->confBaudRate(9600);
  
$serial->deviceOpen();
  
sleep(2);
  
$serial->sendMessage($dainviare);
  
sleep(2);
  
header('Location: setpoint.php');
?>


Il primo carattere (a) serve ad arduino per capire di che tipo di riga si tratta per poi fargli compiere la scrittura sulla eprom dei due valori successivi separati da ";".
Dopo aver passato la stringa su seriale ritorno alla pagina setpoint
Per risolvere il problema ho dovuto mettere i due sleep di 2 secondi (uno non basta).
Quello dopo l'apertura della seriale l'avevo già messo mentre quello prima di tornare alla apgina setpoint no e questo causava il problema della non scrittura.
Sicuramente così funziona ma sono abbastanza perplesso di questa cosa.
E' logico così?
Logged

0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Io non conosco php, leggo il codice e ne intuisco cosa fà, ma ho un dubbio?

<?php

?>

Mi sembra un blocco { code... }, li dentro le variabili sono locali se abbandoni quel blocco tornando alla pagina principale, la variabile $serial esce dallo scope e il garbage la fa fuori, ci potrebbe anche essere un meccanismo automatico tipo distruttore C++, dove viene detto di chiudere il device in uso.

In C++, specie con Qt un device viene aperto ma non è necessario chiamare close, perchè appena l'oggetto esce fuori scope viene chiamato il distruttore di oggetto che prima di ogni cosa chiude il file.

Cosa accade se il file viene chiuso, si resetta Arduino? Giuro non me lo ricordo per adesso ho altro per la testa, prova il codice python al link cerca di capirci qualcosa, fai esperimenti vedi tu, indaga sul codice del bootloader di arduino per vedere come si comporta ecc.

Allora un barlume di luce, inizialmente aperta la connessione parli con il bootloader, attendi che questo avvi il programma utente e invia i dati. Quanto devi attendere, cambia da Arduino ad arduino o meglio in base al bootloader.

Se hai bisogno di altro, spara pure.


Ciao.

Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Riprendo questo topic perchè ho nuovamente dei problemi con la seriale che non mi spiego.

Tralasciando il codice utlizzato per recuperare i dati dalla seriale, Arduino restituisce il seguente tracciato record:
EC; PH; Temperatura; Stato Digital PIN 2; Stato Digital PIN 4; Stato Digital PIN 7; Data
I primi tre valore sono rilevati da delle sonde ma questo non importa, mi importerebbe invece capire il perchè del diverso comportamente a seconda delle condizioni che descrivo sotto. E' molto importante, per ogni caso, seguire tutti i passi che ho effettuato
Con sketch caricato su arduino:

1) riavvio il pc a cui è collegato Arduino su USB; apro Arduino IDE; apro il serial monitor.
    Mi viene restituita la seguente stringa:
    2399;14.0;18.12;1;1;0;3/4/2013 10:15
    Perfetto, tutto funziona correttamente
2) riavvio il pc a cui è collegato Arduino su USB;
    lancio il seguente programma scritto il python:
   
Code:
import serial
arduino=serial.Serial('/dev/ttyACM0')
arduino.write('c1') #quando Arduino riceve questa string, mi risponde mandandomi certi dati
print arduino.readline()
    Il programma "si pianta".
    Faccio un CTRL z
    Rilancio il programma e adesso tutto funziona perfettamente e mi viene restituito
    2279;14.0;18.15;1;1;0;3/4/2013 10:20
3) riavvio il pc a cui è collegato Arduino su USB;
    lancio il seguente programma scritto il python:
   
Code:
import serial
import time
arduino=serial.Serial('/dev/ttyACM0')
time.sleep (2)
arduino.write('c1') #quando Arduino riceve questa string, mi risponde mandandomi certi dati
print arduino.readline()
   (ho aggiunto una pausa di 2 secondi dopo aver apero il collegamento con la seriale)
   Il programma mi restituisce:
   2100;0.0;0.00;0;0;0;3/4/2013 10:24
   In pratica non vengono rilevati i valori di PH; Temperatura; Stato Digital PIN 2; Stato    Digital PIN 4; Stato Digital PIN 7
   mentre vengono rilevati l'EC e la data.
   Se rilancio il programma il comportamento è sempre lo stesso.
   
   A questo punto apro Arduino IDE, apro il serial monitor e vedo
   2479;14.0;18.06;1;1;0;3/4/2013 10:26
   Sul serial monitor è OK
   
   Chiudo il serial monitor e rilancio il solito programma di python e ottengo
   2343;0.0;0.00;0;0;0;3/4/2013 10:27
   Ho nuovamento perso i soliti valori

   Riapro Arduino IDE e il suo serial monitor e lo lascio aperto
   Eseguo il solito programma in python e vedo che i valori compaiono sul serial monitor di Arduino e tra l'altro sono corretti:
   2322;14.0;18.06;1;1;0;3/4/2013 10:28


Esiste un comando da lanciare sulla seriale per fare in modo che dopo un riavvio la seriale risponda a python nella maniera corretta, come dopo un CTRL z?
   

   

Logged

0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A distanza e senza il codice di arduino non so dirti altro. Io ho usato Arduino 2009, con su un programma che deve dialogare tramite seriale con un ATmega644, quando ho scritto il codice per 2009 non avevo scritto il codice per il 644 e quindi usavo python per testare la comunicazione. Ti allego il file che nel mio caso simula ciò che fa il 644.

Ti consiglio di prendere il codice che hai scritto per arduino e purgarlo di ciò che non è utile per la comunicazione, i dati che spedisci rendili statici nella stessa forma, cioè rispettando il protocollo "2279;14.0;18.15;1;1;0;3/4/2013 10:20", e usa questo codice per fare i testi di comunicazione, in questo modo puoi anche postare il codice senza superare il limite di caratteri per post.

Non mi chiedere dettagli sul codice python perchè non so rispondere, il programma risale a 2 anni fa. Ricordo solo che io ho avuto problemi con il ritorno carrello "\n" e qualche problema simile al tuo, cioè ora funziona ora no, ora si ecc, ora funziona solo con python ora solo con il serial monitor, ecc.


Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import serial 
import time   
# imposto la porta 
ser = serial.Serial(port='/dev/ttyUSB0', 
    baudrate=115600, 
    bytesize=8, 
    parity='N', 
    stopbits=serial.STOPBITS_ONE, 
    timeout=None, 
    xonxoff=False, 
    rtscts=False, 
    writeTimeout=None, 
    dsrdtr=False) 
   

ser.open()
#ser.flushInput()

#print dir(ser)
cb = ''
message = ''
identity = False
#for i in xrange(10):
    #time.sleep(2)

   
#    ser.write('g5000')
#    ser.write('g0')
    #time.sleep(2)
    #ser.write('A')

#print "Clear DTR and RTS to unload the RESET capacitor" 
#ser.setRTS(False)
#ser.setDTR(False)
#print "attende x tempo"
#time.sleep(1)
#print "Set DTR and RTS back to high"
#ser.setRTS(True)
#ser.setDTR(True)
#print "attende x tempo"
#time.sleep(0.6)
#print "scrive 0x30, 0x20"
#ser.write(chr(0x30))
#ser.write(chr(0x20))
#print ord(ser.read())
#print "scrive 0x75, 0x20"
#ser.write(chr(0x75))
#ser.write(chr(0x20))
#print hex(ord(ser.read()))
#print hex(ord(ser.read()))
#print hex(ord(ser.read()))
#print hex(ord(ser.read()))
#print hex(ord(ser.read()))
# reset e identificazione arduino terminata, probabilmente
# arduino 2009 non ha più il bootloader
# legge byte, si aspetta 0x2 dal master
SLAVE_ID = 5
THERE_IS_RESUME = 48 # 0x31 "1"  49
NO_RESUME = 48       # 0x30 "0"
masterIdRequest = ord(ser.read(1))

# entrano solo numeri pari
if (masterIdRequest & 1) == 0:
  if masterIdRequest == 2:
    print "ricevuta richiesta di idendificazione da Master: ",masterIdRequest
    print "rispondo inviando SLAVE_ID", SLAVE_ID
    ser.write(chr(SLAVE_ID))
    ser.write(chr(SLAVE_ID))
    ser.flushInput();
    # controllo ridondante sullo slave da fare in loop
    # il master invia e riceve ciclando 3 volte qui e la stessa cosa
    # invertita riceve e invia
    checkResume = ord(ser.read(1))     
    ser.write(chr(THERE_IS_RESUME))
   
    checkResume = ord(ser.read(1))
    ser.write(chr(THERE_IS_RESUME))
    checkResume = ord(ser.read(1))
    ser.write(chr(THERE_IS_RESUME))
     
   
   





#print "scrive 65, 80"
#ser.write(chr(0x41))
#ser.write(chr(0x80))
#ser.write(chr(0x20))
#print ord(ser.read())
#print ord(ser.read())
#print ord(ser.read())
#print ser.read()

i = 0
#pulse_width = []
lines = []
#ser.write("S")
#ser.write("Z")
busy = 0
#while True:
   
#    i += 1
#    if i > 212000:
#        break
    #if i == 0:
        ###break
        #time.sleep(4.2)
        #ser.write("g6000")
        #i = 1
    #elif i == 1:   
        #time.sleep(4.2)
        #ser.write("g0")
        #i = 0
#    cn = ser.inWaiting()

#    if cn != 0:
#        date = ''
#        for t in xrange(cn):
#            date = date + ser.read()
#            print(date)
       
        #if True:
        #lines.append(date)   
            #if i == 2:
                #i = 1
            #elif i == 3:
                ##print i
                #i = 0
        #else:
            #busy += 1
            #print "busy"
            #if busy > 3:
                #ser.write("\n")
                #busy = 0
ser.close()
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Niente, non ci salto fuori, se uso il serial monitor di arduino i valori sono corretti mentre se uso python (o php) alcuni dati non mi arrivano corretti.

Ho struttato il codice
Code:
import serial 
import time   
# imposto la porta 
ser = serial.Serial(port='/dev/ttyUSB0', 
    baudrate=115600, 
    bytesize=8, 
    parity='N', 
    stopbits=serial.STOPBITS_ONE, 
    timeout=None, 
    xonxoff=False, 
    rtscts=False, 
    writeTimeout=None, 
    dsrdtr=False) 
ser.open()

per inizializzareil collegamento ma il problema persiste.
Spero che qualcun'altro abbia avuto lo stesso problema e mi aiuti.
Rimango del parere che ci possa essere un comando da "sparare" all'inizio della comunicazione per "svegliare" arduino. Tipo:
eseguo il codice python
Code:
import serial

arduino=serial.Serial('/dev/ttyACM0')

arduino.write('b1')
print arduino.readline(

e si pianta. Premo CTRL z e prende a funzionare alla perfezione. Ecco, bisognerebbe anticipare quel "si pianta e premo CTRL z".
Vi prego, se avete idee ditemi pure....
Logged

Cagliari, Italy
Online Online
Tesla Member
***
Karma: 102
Posts: 6546
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi pare di capire che hai problemi quando lanci il programma prima che Arduino abbia inizializzato la seriale.
Dopo l'inizializzazione fai accedere ad esempio il pin 13. Cosi vedi visivamente cosa sta combinando Arduino.

Se apri il serial monitor Arduino si resetta, viene reinizializzato e lo sketch parte dall'inizio. Non che il problema e nel codice Arduino e non in Pyton?
Anche perché questo contrasta con la tesi di prima, ovvero fai ripartire Arduino con il programma Pyton già in esecuzione.

Esiste un comando in pyton per bloccare l'esecuzione attendendo che sia stata inizializzata la seriale da parte di Arduino?
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi pare di capire che hai problemi quando lanci il programma prima che Arduino abbia inizializzato la seriale.
Dopo l'inizializzazione fai accedere ad esempio il pin 13. Cosi vedi visivamente cosa sta combinando Arduino.

Se apri il serial monitor Arduino si resetta, viene reinizializzato e lo sketch parte dall'inizio. Non che il problema e nel codice Arduino e non in Pyton?
Anche perché questo contrasta con la tesi di prima, ovvero fai ripartire Arduino con il programma Pyton già in esecuzione.

In teoria è il contrario: io alimento arduino con un alimentatore e quindi rimane sempre acceso.
Quello che riavvio è il pc collegato a Arduino con USB.
Logged

Pages: [1] 2 3   Go Up
Jump to: