Per maggiori dettagli di come vengono inviati i comandi alle Philips Hue tornate ai miei post precedenti sull'argomento.
Per inviare il codice colore e la luminosità ho predisposto una funzione chiamata setHue(X,Y,B) dove X e Y rappresentano i codice colore 0-255 e B la luminosità sempre in range 0-255.
void httpRequest(String hueCmd) { Serial.println(hueCmd); Serial.println("httpRequest..."); if (client.connect(ipAddressHue, 80)) { if (client.connected()) { Serial.println("connecting..."); client.print("PUT /api/"); client.print(hueUsername); client.print("/lights/"); client.print(hueLight + 1); // hueLight zero based, add 1 client.println("/state HTTP/1.1"); client.println("keep-alive"); client.print("Host: "); client.println(hueHubIP); client.print("Content-Length: "); client.println(hueCmd.length()); client.println("Content-Type: text/plain;charset=UTF-8"); client.println(); // blank line before body client.println(hueCmd); // Hue command } // close the connection client.stop(); Serial.println("disconnected"); } else { Serial.println("connection failed"); Serial.println(); Serial.println("disconnecting."); client.stop(); } } double x,y; char buf[32]; // needs to be at least large enough to fit the formatted text char buf2[32]; // needs to be at least large enough to fit the formatted text String hueCommand=""; void setHue(long X, long Y , long B) { if (X+Y+B<120) { if (isOn=HIGH) { hueCommand="{ \"on\":false }"; isOn=LOW; } } else { x=(double)((double)X/(double)255); y=(double)((double)Y/(double)255); dtostrf(x,2,1,buf); dtostrf(y,2,1,buf2); hueCommand="{ \"on\":true, \"bri\":" + String(B) + " , \"xy\":[" + String(buf) +"," + buf2 +"] }"; isOn=HIGH; } httpRequest(hueCommand); }
La parte più interessante è sicuramente quello che sta a monte, ovvero la misurazione del tempo di carica. Il tutto è fatto cambiando rapidamente lo stato del pin e misurandone il tempo di carica, poi "normalizzato" come valore di distanza tramite radice quadrata (vedi post precedente).
Le misurazioni avvengono a gruppi di 3, in modo poi da ottenere un valore medio, molto più stabile.
Le letture avvengono accedendo in modo diretto ai registri di arduino. (PINB e PIND).
for (int i=0;i<3;i++) { normalizedA+= normalize(zeroA,getDistance(time(SENSOR_A , B00000001)),1000); normalizedB+= normalize(zeroB,getDistance(time(SENSOR_B , B00000010)),500); normalizedC+= normalize(zeroC,getDistance(time(SENSOR_C , B10000000)),500); normalizedD+= normalize(zeroD,getDistance(time(SENSOR_D , B01000000)),500); normalizedE+= normalize(zeroE,getDistance(time(SENSOR_E , B00100000)),500); } normalizedA=normalizedA/3; normalizedB=normalizedB/3; normalizedC=normalizedC/3; normalizedD=normalizedD/3; normalizedE=normalizedE/3; long time(int pin, byte mask) { unsigned long count = 0, total = 0; while(checkTimer() < refresh) { // pinMode is about 6 times slower than assigning // DDRB directly, but that pause is important pinMode(pin, OUTPUT); PORTB = 0; PORTD = 0; pinMode(pin, INPUT); if (pin<=7 ) { while((PIND & mask) == 0) count++; } else { while((PINB & mask) == 0) count++; } total++; } startTimer(); return (count << resolution) / total; } long getDistance(long value) { return (long) ((double)1)/sqrt((double)(value/2))*1000000000; } long normalize(long zeroValue, long distanceValue, long scaleValue) { long normalized=0; normalized=zeroValue - distanceValue ; if (normalized<0) { normalized=0; }; normalized=normalized/scaleValue; if (normalized>255) {normalized=255;}; return normalized; }
Nessun commento:
Posta un commento