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