Sonoff B1 SUPLA

Post Reply
Beku
Posts: 14
Joined: Tue Nov 06, 2018 1:49 pm

Thu Jan 17, 2019 9:14 pm

Cześć,

Dzisiaj przyszła do mnie żarówka jak w temacie. Pobawiłem się trochę korzystając z zasobów internetu i efekt poniżej.

Skorzystałem z Arduino IDE i biblioteki SuplaDevice (kod w załączniku).
Nie jest doskonały i wymaga poprawek i optymalizacji ale dla dzisiejszego efektu wystarczy :)

Code: Select all


#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define SUPLADEVICE_CPP
#include <SuplaDevice.h>

WiFiClient client;

// Setup Supla connection
const char* ssid     = "XXXX";
const char* password = "XXXX";

unsigned char _red = 0;
unsigned char _green = 0;
unsigned char _blue = 0;
unsigned char _color_brightness = 0;
unsigned char _brightness = 0;

uint8_t light_pdi_pin;
uint8_t light_pdcki_pin;

float light_hue = 0.0;
float light_saturation = 0.0;

typedef struct {
    double h;
    double s;
    double v;
} hsv;


extern "C" {
  void os_delay_us(unsigned int);
}

hsv rgb2hsv(int rgb)
{
    hsv         out;
    double      min, max, delta;

    unsigned char r = (unsigned char)((rgb & 0x00FF0000) >> 16);
    unsigned char g = (unsigned char)((rgb & 0x0000FF00) >> 8);
    unsigned char b = (unsigned char)(rgb & 0x000000FF);

    min = r < g ? r : g;
    min = min  < b ? min  : b;

    max = r > g ? r : g;
    max = max  > b ? max  : b;

    out.v = max;
    delta = max - min;
    if (delta < 0.00001)
    {
        out.s = 0;
        out.h = 0;
        return out;
    }
    if( max > 0.0 ) {
        out.s = (delta / max);
    } else {
        out.s = 0.0;
        out.h = -1;
        return out;
    }
    if( r >= max )
        out.h = ( g - b ) / delta;
    else
    if( g >= max )
        out.h = 2.0 + ( b - r ) / delta;
    else
        out.h = 4.0 + ( r - g ) / delta;

    out.h *= 60.0;

    if( out.h < 0.0 )
        out.h += 360.0;

    return out;
}

int hsv2rgb(hsv in)
{
    double      hh, p, q, t, ff;
    long        i;

    unsigned char r,g,b;
    int rgb = 0;

    if(in.s <= 0.0) {       // < is bogus, just shuts up warnings
        r = in.v;
        g = in.v;
        b = in.v;

        rgb = r & 0xFF; rgb<<=8;
        rgb |= g & 0xFF; rgb<<=8;
        rgb |= b & 0xFF;

        return rgb;
    }
    hh = in.h;
    if(hh >= 360.0) hh = 0.0;
    hh /= 60.0;
    i = (long)hh;
    ff = hh - i;
    p = in.v * (1.0 - in.s);
    q = in.v * (1.0 - (in.s * ff));
    t = in.v * (1.0 - (in.s * (1.0 - ff)));

    switch(i) {
    case 0:
        r = in.v; g = t; b = p;
        break;
    case 1:
        r = q; g = in.v; b = p;
        break;
    case 2:
        r = p; g = in.v; b = t;
        break;
    case 3:
        r = p; g = q; b = in.v;
        break;
    case 4:
        r = t; g = p; b = in.v;
        break;
    case 5:
    default:
        r = in.v; g = p; b = q;
        break;
    }

    rgb = r & 0xFF; rgb<<=8;
    rgb |= g & 0xFF; rgb<<=8;
    rgb |= b & 0xFF;

    return rgb;
}


void LightMy92x1Write(uint8_t data)
{
  for (uint8_t i = 0; i < 4; i++) {     // Send 8bit Data
    digitalWrite(light_pdcki_pin, LOW);
    digitalWrite(light_pdi_pin, (data & 0x80));
    digitalWrite(light_pdcki_pin, HIGH);
    data = data << 1;
    digitalWrite(light_pdi_pin, (data & 0x80));
    digitalWrite(light_pdcki_pin, LOW);
    digitalWrite(light_pdi_pin, LOW);
    data = data << 1;
  }
}

void get_rgbw_value(int channelNumber, unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *color_brightness, unsigned char *brightness) {

  *brightness = _brightness;
  *color_brightness= _color_brightness;
  *red = _red;
  *green = _green;
  *blue = _blue;
}


void set_rgbw() {

  hsv _hsv;
  int rgb = _red & 0xFF; rgb<<=8;
  rgb |= _green & 0xFF; rgb<<=8;
  rgb |= _blue & 0xFF;
  
  _hsv = rgb2hsv(rgb);
  _hsv.v = 255 * _color_brightness / 100;

  rgb = hsv2rgb(_hsv);

  unsigned char r = (unsigned char)((rgb & 0x00FF0000) >> 16);
  unsigned char g = (unsigned char)((rgb & 0x0000FF00) >> 8);
  unsigned char b = (unsigned char)(rgb & 0x000000FF);

  uint8_t duty[6] = {(_brightness * 255) / 100, (_brightness * 255) / 100, 0, g, r, b };  // Definition for RGBWC channels

  os_delay_us(12);                      // TStop > 12us.
  for (uint8_t channel = 0; channel < 6; channel++) {
    LightMy92x1Write(duty[channel]);  // Send 8bit Data
  }
  
  os_delay_us(12);                      // TStart > 12us. Ready for send DI pulse.
  LightDiPulse(8);                      // Send 8 DI pulse. After 8 pulse falling edge, store old data.
  os_delay_us(12);                      // TStop > 12us.
}

void set_rgbw_value(int channelNumber, unsigned char red, unsigned char green, unsigned char blue, unsigned char color_brightness, unsigned char brightness) {
    
    _brightness = brightness;
    _color_brightness= color_brightness;
  
    _red = red;
    _green = green;
    _blue = blue;  
    
    set_rgbw();
}

void LightDiPulse(uint8_t times)
{
  for (uint8_t i = 0; i < times; i++) {
    digitalWrite(light_pdi_pin, HIGH);
    digitalWrite(light_pdi_pin, LOW);
  }
}

void LightDckiPulse(uint8_t times)
{
  for (uint8_t i = 0; i < times; i++) {
    digitalWrite(light_pdcki_pin, HIGH);
    digitalWrite(light_pdcki_pin, LOW);
  }
}

void LightMy92x1Init(void)
{
  uint8_t chips = 2;                    // 1 (AiLight)
  
  LightDckiPulse(chips * 32);           // Clear all duty register
  os_delay_us(12);                      // TStop > 12us.
  // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12
  // pulse's rising edge convert to command mode.
  LightDiPulse(12);
  os_delay_us(12);                      // Delay >12us, begin send CMD data
  for (uint8_t n = 0; n < chips; n++) { // Send CMD data
    LightMy92x1Write(0x18);             // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM
  }
  os_delay_us(12);                      // TStart > 12us. Delay 12 us.
  // Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and
  // at 16 pulse's falling edge convert to duty mode.
  LightDiPulse(16);
  os_delay_us(12);                      // TStop > 12us.
}

void setup() {
  Serial.begin(9600);
  delay(10);
  Serial.write("test");
  // Replace the falowing GUID
  char GUID[SUPLA_GUID_SIZE] = {0x20,0x09,0xFA,0xF8,0x1D,0x00,0x58,0x3C,0x76,0x2D,0x0B,0x86,0x7D,0x63,0xB0,0xF9};
  // with GUID that you can retrieve from https://www.supla.org/arduino/get-guid

  // Ethernet MAC address
  uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};


  light_pdi_pin = 12;
  light_pdcki_pin = 14;
  
  pinMode(light_pdi_pin, OUTPUT);
  pinMode(light_pdcki_pin, OUTPUT);
  digitalWrite(light_pdi_pin, LOW);
  digitalWrite(light_pdcki_pin, LOW);
  
  LightMy92x1Init();
  /*
   * Having your device already registered at cloud.supla.org,
   * you want to change CHANNEL sequence or remove any of them,
   * then you must also remove the device itself from cloud.supla.org.
   * Otherwise you will get "Channel conflict!" error.
   */
  SuplaDevice.setRGBWCallbacks(&get_rgbw_value, &set_rgbw_value);
  SuplaDevice.addRgbControllerAndDimmer();
    
  
  SuplaDevice.begin(GUID,              // Global Unique Identifier 
                    mac,               // Ethernet MAC address
                    "srv",  // SUPLA server address
                    0,                 // Location ID 
                    "XXXX");               // Location Password
  
}

void loop() {

   if (WiFi.status() != WL_CONNECTED) // Jeżeli sieć WiFi nie jest podłączona, wywołaj procedurę łączenia
  {
    WiFi_up();
  }
  SuplaDevice.iterate();
}

// Supla.org ethernet layer
    int supla_arduino_tcp_read(void *buf, int count) {
        _supla_int_t size = client.available();
       
        if ( size > 0 ) {
            if ( size > count ) size = count;
            return client.read((uint8_t *)buf, size);
        };
    
        return -1;
    };
    
    int supla_arduino_tcp_write(void *buf, int count) {
        return client.write((const uint8_t *)buf, count);
    };
    
    bool supla_arduino_svr_connect(const char *server, int port) {
          return client.connect(server, 2015);
    }
    
    bool supla_arduino_svr_connected(void) {
          return client.connected();
    }
    
    void supla_arduino_svr_disconnect(void) {
         client.stop();
    }
    
    void supla_arduino_eth_setup(uint8_t mac[6], IPAddress *ip) {

       WiFi_up();
    }

SuplaDeviceCallbacks supla_arduino_get_callbacks(void) {
          SuplaDeviceCallbacks cb;
          
          cb.tcp_read = &supla_arduino_tcp_read;
          cb.tcp_write = &supla_arduino_tcp_write;
          cb.eth_setup = &supla_arduino_eth_setup;
          cb.svr_connected = &supla_arduino_svr_connected;
          cb.svr_connect = &supla_arduino_svr_connect;
          cb.svr_disconnect = &supla_arduino_svr_disconnect;
          cb.get_temperature = NULL;
          cb.get_temperature_and_humidity = NULL;
          cb.get_rgbw_value = NULL;
          cb.set_rgbw_value = NULL;
          
          return cb;
}

void WiFi_up() // Procedura podłączenia do sieci WiFi
{
  Serial.print("Proba podlaczenia do sieci ");
  Serial.println(ssid);

  WiFi.begin(ssid, password); // Próba podłączenia do sieci


  for (int x = 60; x > 0; x--) // Powtarzaj pętlę maksymanie maksymalnie 30 sekund (ponieważ przy każdym elsie jest 0,5 sekundy zwłoki)
  {
    if (WiFi.status() == WL_CONNECTED) // Jezeli WiFi jest podłączone
    {
      break;                           // to zatrzymaj pętlę
    }
    else                                 // w przeciwnym wypadku
    {
      Serial.print(".");               // wystaw na serial .
      delay(500);                      // i czekaj 0,5 sekundy
    }

  }

  if (WiFi.status() == WL_CONNECTED) // Jeżeli połączenie z siecią zostało nawiązane, wyślij na serial jego parametry
  {
    Serial.println("");
    Serial.println("Polaczenie nawiazane");
    Serial.println("Adres IP: ");
    Serial.print(WiFi.localIP());
    Serial.print(" / ");
    Serial.println(WiFi.subnetMask());
    Serial.print("Brama: ");
    Serial.println(WiFi.gatewayIP());
    long rssi = WiFi.RSSI();
    Serial.print("Sila sygnalu (RSSI): ");
    Serial.print(rssi);
    Serial.println(" dBm");
  }
  else    // w przeciwnym wypadku poinformuj przez serial o nieudanej próbie
  {
    Serial.println("");
    Serial.println("Polaczenia nie udalo sie nawiazac");
  }
}
Poniżej filmik

https://youtu.be/9-9kH-GmFoI
Attachments
IMG-20190117-WA0003.jpg
IMG-20190117-WA0003.jpg (84.48 KiB) Viewed 3972 times
IMG-20190117-WA0005.jpg
IMG-20190117-WA0005.jpg (79.18 KiB) Viewed 3972 times
IMG-20190117-WA0007.jpg
IMG-20190117-WA0007.jpg (44.94 KiB) Viewed 3972 times
User avatar
pilcu
Posts: 97
Joined: Fri Jan 11, 2019 9:49 am
Location: Wrocław

Wed May 29, 2019 9:12 am

W którym miejscu w kodzie należy dodać linijkę wyłączającą rozgłaszanie sieci przez żarówkę?
User avatar
wojtas567
Posts: 1603
Joined: Sun Apr 03, 2016 7:16 pm
Location: Olsztyn

Wed May 29, 2019 9:58 am

Ja mniej więcej w tym miejscu mam ten wpis

Code: Select all

void setup() {
//  Serial.begin(115200);
  delay(10);
  EEPROM.begin(512);                               //-------------- Start EEprom ------------- EEprom

  WiFi.softAPdisconnect(true);                         // wyłączenie rozgłaszania sieci ESP
  wifi_station_set_hostname("E_Supla_lampa");       // zmiana nazwy ESP w sieci lokalnej
//  WiFi.setOutputPower(10);                       //Ograniczanie mocy wyjściowej (0 - 20.5)
...
Pozdrawiam
Wojtek
User avatar
pilcu
Posts: 97
Joined: Fri Jan 11, 2019 9:49 am
Location: Wrocław

Thu May 30, 2019 7:58 am

Dzięki wielkie Wojtku.
User avatar
wojtas567
Posts: 1603
Joined: Sun Apr 03, 2016 7:16 pm
Location: Olsztyn

Thu May 30, 2019 8:20 am

:D :D
Pozdrawiam
Wojtek
Post Reply