LEOSER WEB


 

postheadericon ARDUINO

Controllo Arduino con PHP/PERL, name DOMINO

Controllo Arduino con Estensione Domotica ed accesso da remoto - i2c.

Questa nuova estensione del progetto permettera' il controllo, sempre attraverso l'interfaccia standard, di 2 o piu arduino in i2c mediante la libreria Wire.
Mi prefiggo di modificare un pochino la logica dell'i2c, dove e' previsto uno o piu' master e uno o piu' slave, ponendo tutti sullo stesso livello.
Il fatto di avere 1 master e piu slave, se non pone un problema per un solo slave, lo potrebbe fare per piu' slave, considerato che il master sarebbe l'arduino collegato fisicamente al pc che dovrebbe, oltre che smistare le richieste e gestire le risposte, colloquiare anche con la sua parte in campo; forse un po' pesante.
Quindi l'ideale e' che tutti si possano comportare all'occorrenza sia come master che come slave; questo permette inoltre di avere anche lo slave fisicamente connesso ad un pc con il programma PHP o PERL che lo controlla; un bell'incrocio di informazioni!

Per i collegamenti, se sono solo 2 arduino, bastano i pull-up interni. Ricordate il ground e vcc in comune, analog4 e analog5 dei due arduino collegati tra di loro; ogni arduino, anche per comodita' di programmazione, l'ho collegato ad un pc diverso.
Oltre alle modifiche che si dovranno apportare al codice PHP o PERL, il trucco e' nello sketch che, oltre a funzionare come quello gia' disponibile nella versione PHP, conterra' alcune modifiche.
Devo ancora ultimare qualche test ma vi comincio a mettere di seguito lo sketch di prova;al momento non so che tipo di problemi, una volta inglobato nello sketch della versione PHP, possano venire fuori; la logica delle interruzioni prevede che , dentro la routine, si faccia proprio lo stretto indispensabile e quindi ci sara' da ridisegnare un po' la struttura del programma; comunque, questo e' lo sketch di prova (ide 023 e 2 arduino 2009):

															#define THIS_ARDUINO_ID 1  // Cambiare la id per ogni postazione
															#include <Wire.h>
															String readString;
															int flag_not_local=0, i, id_arduino_to;
															char id[4];

															//  IDE 023
															//  con la vecchia libreira wire sono massimo 32 caratteri compreso il null finale
															//  id_arduino_toPacchetto  senza spazi ne delimitatori
															//  |   3bytes   |  max 28 |
															//  esempio ; 002d13#11   accende pin 13 in id 2
															//  se id_arduino_id = THIS_ARDUINO_ID il comando e' eseguito localmente
															//  il flag not_local intercetta il receive_event da interrupt sulla chiamata Wire.requestFrom
															//  QUESTO SAREBBE L'UNICO SKETCH DA CARICARE SU TUTTI GLI ARDUINI DELLA RETE
															//  L'UNICA MODIFICA E' L'ID DELL'ARDUINO NELLA DEFINE
															//
															//  nell'esempio ho impostato la id degli arduini a 1 e 2
															//  uno manda all'altro e l'altro risponde con la stringa ciao da

															void setup()
															{
																Wire.begin(THIS_ARDUINO_ID);
																Wire.onReceive(receiveEvent); // registra evento
																Wire.onRequest(requestEvent); // registra evento
																Serial.begin(115200);
																analogReference(DEFAULT);
															}
															void loop()
															{
																if (Serial.available() > 0)
																{
																	readString="";   
																	while (Serial.available()) 
																	{
																		delay(10);
																		if (Serial.available() >0) 
																		{
																			char c = Serial.read();
																			readString += c;
																		}
																	}
																	readString+="\0";

																	// A chi va? 
																	String id_station=readString.substring(1,3);
																	id_station+="\0";
																	id_station.toCharArray(id, sizeof(id));
																	id_arduino_to = atoi(id);
																	readString=readString.substring(3);
																	
																	if(id_arduino_to == THIS_ARDUINO_ID)
																	{
																		// E' UN COMANDO SU QUESTO ARDUINO
																		flag_not_local=0;
																		Serial.println("locale "+readString);
																	}
																	else
																	{
																		// E' UN COMANDO CHE VA SU UN'ALTRO ARDUINO 
																		Serial.println("INPUT STRING "+readString);
																		wire_send(id_arduino_to);
																		readString="";
																		flag_not_local=1;
																		// importantissimo ! e' possibile che su richieste pesanti si debba usare 
																		// un delay maggiore per dare tempo all'arduino target di prepare la risposta 
																		delay(5); 
																		Wire.requestFrom(id_arduino_to,31);
																		// qui manda un classico comando MASTER ....ma come, non e' il master
																		readString="";
																		// e qui si prende la risposta 
																		while (Wire.available())
																		{
																		char c = Wire.receive();
																		readString+= c;
																		}  
																		readString+= "\0";
																		Serial.println("Ricevuto "+readString);
																	}
																}
															}

															void wire_send(int id_arduino_to)
															{
																char w_send[31];
																readString.toCharArray(w_send, sizeof(w_send));
																w_send[31]= '\0';
																int i;
																Wire.beginTransmission(id_arduino_to);
																while (w_send[i])
																{
																	Wire.send(w_send[i++]); 
																}
																Wire.endTransmission();
																Serial.println("Inviato "+readString);
															}

															void receiveEvent(int howMany)
															{
															//  Il flag_no_local e' necessario in quando, dalla requestfrom, la routine sarebbe attivata dall'arrivo dei caratteri. 
															//	Il flag_no_local evita questo in quando abbiamo gia' ricevuto 
															//	L'uso di nointerrupts / interrupts ho visto che non funziona benissimo 
															  if (flag_not_local==0)
															  {
																// qui riceve un stringa (comando) 
																readString="";
																while (Wire.available()>0)
																{
																	char c = Wire.receive();
																	readString+= c;
																}  
																readString+= "\0";
																Serial.println("Ricevuto "+readString);
																
															  }
															flag_not_local=0;
															}

															void requestEvent()
															{
																Serial.println("** Request");
																Wire.send("ciao da 1"); // cambiate gli id
																Serial.println("Inviato ciao da 1 in risposta a 2"); // cambiate gli id
															}
														


FATEMI SAPERE SE VI FUNZIONA!