Lettura seriale Arduino
-
23-08-2019 - |
Domanda
Sto lavorando su un rover controllato dal web e sto utilizzando una porta seriale per comunicare con un Arduino.Ho scritto del PHP che utilizza solo fwrite()
e scrive un ASCII 1 o un ASCII 2 sulla porta seriale.L'Arduino sta ascoltando quella porta e fa cose in base a ciò che sente.So che il mio PHP funziona, perché ogni volta che gli dico di inviare materiale, Arduino lo riceve.Ecco il codice Arduino:
//This listens to the serial port (USB) and does stuff based on what it is hearing.
int motor1Pin = 13; //the first motor's port number
int motor2Pin = 12; //the second motor's port number
int usbnumber = 0; //this variable holds what we are currently reading from serial
void setup() { //call this once at the beginning
pinMode(motor1Pin, OUTPUT);
//Tell arduino that the motor pins are going to be outputs
pinMode(motor2Pin, OUTPUT);
Serial.begin(9600); //start up serial port
}
void loop() { //main loop
if (Serial.available() > 0) { //if there is anything on the serial port, read it
usbnumber = Serial.read(); //store it in the usbnumber variable
}
if (usbnumber > 0) { //if we read something
if (usbnumber = 49){
delay(1000);
digitalWrite(motor1Pin, LOW);
digitalWrite(motor2Pin, LOW); //if we read an ASCII 1, stop
}
if (usbnumber = 50){
delay(1000);
digitalWrite(motor1Pin, HIGH);
digitalWrite(motor2Pin, HIGH); //if we read an ASCII 2, drive forward
}
usbnumber = 0; //reset
}
}
Quindi dovrebbe essere abbastanza semplice.In questo momento, quando invio un ASCII 1 o un ASCII 2, il LED con cui sto testando (sul pin 13) si accende e rimane acceso.Ma se invio un altro ASCII 1 o 2, si spegne e poi si riaccende.L'obiettivo è che si accenda solo se un ASCII 1 è l'ultima cosa inviata e rimane acceso fino a quando un 2 non è l'ultima cosa inviata.
Modificare:Ecco il mio PHP:
<?php
$verz="0.0.2";
$comPort = "com3"; /*change to correct com port */
if (isset($_POST["rcmd"])) {
$rcmd = $_POST["rcmd"];
switch ($rcmd) {
case Stop:
$fp =fopen($comPort, "w");
fwrite($fp, chr(1)); /* this is the number that it will write */
fclose($fp);
break;
case Go:
$fp =fopen($comPort, "w");
fwrite($fp, chr(2)); /* this is the number that it will write */
fclose($fp);
break;
default:
die('???');
}
}
?>
<html>
<head><title>Rover Control</title></head>
<body>
<center><h1>Rover Control</h1><b>Version <?php echo $verz; ?></b></center>
<form method="post" action="<?php echo $PHP_SELF;?>">
<table border="0">
<tr>
<td></td>
<td>
</td>
<td></td>
</tr>
<tr>
<td>
<input type="submit" value="Stop" name="rcmd"><br/>
</td>
<td></td>
<td>
<input type="submit" value="Go" name="rcmd"><br />
</td>
</tr>
<tr>
<td></td>
<td><br><br><br><br><br>
</td>
<td></td>
</tr>
</table>
</form>
</body>
</html>
Soluzione
Se è C allora si ha assegnazione al posto di confronto in entrambe le prove, in modo che entrambi sono true
, così tutte le scritture sono fatte ogni volta. Compilare con elevato livello di allarme (come -Wall -pedantic
in GCC). Prova questo:
int a = 0;
if ( a == 1 ) printf( "a is not one: %d\n", a );
if ( a = 1 ) printf( "a is one: %d\n", a );
Da codice PHP che hai postato (io non sono un esperto qui) sembra che si sta scrivendo binario 1 come char, che non è ASCII 49, ma ASCII 1 (SOH), lo stesso per 2. Prova a cambiare a '1'
in codice PHP (o 1
in codice C).
Ecco un link a qualche articolo su Controllo della porta seriale con PHP - ho cercato su google, nessuna idea della sua qualità - ma non sembra che sia sufficiente scrivere solo un intero in "com1" - che è fuori del mio dominio, quindi buona fortuna:)
Altri suggerimenti
Come ha detto Nikolai, sembra che tu stia facendo un incarico (=) anziché un confronto (==) nelle tue dichiarazioni "se".
Una buona abitudine adottata da alcuni programmatori C è quella di inserire gli rvalue sul lato sinistro dei confronti, in modo che il compilatore generi un errore se si utilizza accidentalmente l'operatore di assegnazione invece dell'operatore di confronto:
if (50 == usbnumber) { // This is okay. ... } if (50 = usbnumber) { // The compiler will generate an error here. ... }
Funziona, indipendentemente dai flag del compilatore o dal livello di avviso che stai utilizzando poiché l'assegnazione a un valore è illegale.
Dovrei aggiungere che questa "rete di sicurezza" non funziona se è necessario confrontare due lvalue.
potrebbe essere troppo tardi, ma penso che il tuo problema è che serial.read () si legge solo un carattere alla volta. Se si invia "49" dal PC, quando si chiama usbnumber = serial.read () si sarebbe trovato "4" il primo ciclo e "9" il secondo ciclo. Nessuno di questi soddisfa le condizioni per cui nulla è stato fatto e usbnumber viene riportato a 0.
Per risolvere, è possibile cambiare condizione serial.available essere
if (Serial.available() == 2)
e poi fare qualcosa di simile a quanto segue per convertire in un numero:
usbnumber = Serial.read() * 10 + Serial.read();
Un'altra opzione è quella di utilizzare la libreria TextFinder - ho scritto un breve tutorial al mio sito web http: //mechariusprojects.com/thunderbolt/?p=60
Mech
Ho trovato la risposta alla ricerca di altre cose, comunque ho appena affrontato (credo) lo stesso problema che aveva.
Nel caso in cui non si è già risolto, penso che i problemi non è il vostro codice, ma il meccanismo di auto-reset sulla scheda Arduino. Cioè:. Ogni volta che una nuova connessione è impostata sulla porta seriale, la scheda Arduino è resettato, questo permette un nuovo firmware da caricare durante la programmazione tramite la porta seriale
Per effettuare questa verifica, provare a lampeggiare un LED nella funzione setup()
, se lampeggia ogni volta che si carica la pagina, questo conferma la mia tesi.
Date un'occhiata qui: http://www.arduino.cc/playground/Main/DisablingAutoResetOnSerialConnection
Ho risolto attaccando la resistenza da 120 Ohm tra + 5V e RESET. Basta ricordarsi di rimuovere ogni volta che si desidera caricare un nuovo firmware per la vostra tavola.