Infineon Team
Published © MIT

IoT Christmas tree

Need a Christmas tree? But you as a tinkerer want to have more than just a standard one-way bio-waste bunch of needles?

AdvancedFull instructions provided2 hours726
IoT Christmas tree

Things used in this project

Hardware components

Wemos D1 Mini
Espressif Wemos D1 Mini
×1
RGB LED Lighting Shield with XMC1202
Infineon RGB LED Lighting Shield with XMC1202
×1
LED Strip, 1 m
LED Strip, 1 m
×1
S2GO PRESSURE DPS368
Infineon S2GO PRESSURE DPS368
DPS422 is obsolete. Recommended to use DPS310 Shield2Go or DPS368 Shield2Go.
×1
AC/DC Power Supply, External Plug In
AC/DC Power Supply, External Plug In
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

IoT Christmas tree

Schematics

Code

Code for ESP8266

C/C++
Open with Arduino IDE and upload to D1 mini
//-----------------------------------------------------------------
//
// Nov-2019 J. Koellermeyer
//
// IFX RGB Shield with remote color mode control based on thingspeak
//
// https://de.mathworks.com/help/thingspeak/mqtt-publish-and-subscribe-with-esp8266.html
//
// board: Wemos D1
//
// requires one thingspeak channel with 4 fields
//
// field1: color id
// field2: heartbeat
// field3: barometric pressure in hPa
// field4: temperature times 10 in Celsius
//
//
//-----------------------------------------------------------------

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#include <Wire.h>
#include <RGBLEDLighting.h>
#include "WiFiAccess.h"
#include <Dps422.h>

//-----------------------------------------------------------------

#define BUILTIN_LED 2

// make sure the proper MAC address is enabled if connecting to IFX idn
const char* ssid     = WIFI_SSID;
const char* password = WIFI_PASSWD;

//-----------------------------------------------------------------

Dps422 Dps422PressureSensor = Dps422();

struct DPSResult {
  int temperature;
  int pressure;
};

//-----------------------------------------------------------------

const char* server  = "mqtt.thingspeak.com";
char mqttUserName[] = "Anything";
char mqttPass[]     = "<thingspeak MQTT password>";
long readChannelID  = 270552;
char readAPIKey[]   = "<thingspeak channel read key>";
long writeChannelID = 270552;
char writeAPIKey[]  = "<thingspeak channel write key>";

int fieldsToPublish[8]={0,1,1,1,0,0,0,0};  // Change to allow multiple fields.
int dataToPublish[8];

WiFiClient client;
PubSubClient mqttClient( client );

//-----------------------------------------------------------------

InfineonRGB LEDS;

int changeFlag = 0;  // set if MQTT subscribe is triggered

int brightness;
int brightness_change_default = 40;
int brightness_change         = 40;
bool brightness_decrease      = false;

// trigger to see if device is still alive/online
unsigned long heartbeatIntervall = 5 * 60 * 1000; // 5 minutes
unsigned long lastHeartbeat      = 0;

// pressure change
unsigned long lastDebounceTimePressure = 0;
unsigned long debouncePressureDelay    = 100;
bool pressureAboveThres     = false;
bool lastPressureAboveThres = false;

int pressureRef = 0;
int tempRef     = 0;

/*
typedef enum{
  White, Silver, Gray, Black, Red, Maroon, Yellow, Olive, Lime, Green, Aqua, Teal, Blue, Navy, Fuchsia, Purple
  }Colours;
*/

//-----------------------------------------------------------------

void setup() {

  Serial.begin(9600);

  LEDS.begin();    // Cycle and set everything to zero.

  delay(10);
  
  //led_test();
    
  pinMode(BUILTIN_LED, OUTPUT);
  digitalWrite(BUILTIN_LED, LOW);

  WiFi.mode(WIFI_STA);

//  mac_address();

//  scan_wifi();
//  delay(10000);
  
  wificonnect();

  mqttClient.setServer( server, 1883 );                 // Set the MQTT broker details.
  mqttClient.setCallback( mqttSubscriptionCallback );   // Set the MQTT message handler function.

  delay(10);

  setLEDMode(2);

  delay(10);

  //------------------------------------------------------------- 

  Dps422PressureSensor.begin(Wire);
  delay(10);
  measurePressure();
  delay(10);

  DPSResult a = measurePressure();
  pressureRef = a.pressure;
  tempRef     = a.temperature;
  Serial.print("Reference pressure: ");
  Serial.println(pressureRef);
  Serial.print("Reference temperature: ");
  Serial.println(tempRef/10.0);

  delay(10);

  //------------------------------------------------------------- 

  // publish heartbeat to channel 2
  dataToPublish[1] = 1;
  dataToPublish[2] = pressureRef;
  dataToPublish[3] = tempRef;
  mqttPublish( writeChannelID, writeAPIKey, fieldsToPublish, dataToPublish );

  delay(10);

}


//-------------------------------------------------------------------------------------

void loop() {

  wificonnect();

  if (!mqttClient.connected())    {
    mqttConnect(); // Connect if MQTT client is not connected.
    if(mqttSubscribe( readChannelID,1,readAPIKey,0 ) == 1 ){
      Serial.println( "MQTT subscribed" );
    } else {
      Serial.println( "MQTT NOT subscribed" );
    }
  }
    
  mqttClient.loop(); // Call the loop to maintain connection to the server.                         

  // MQTT value changed
  if (changeFlag){
    changeFlag = 0;
  }
    
  delay(1);

  //--------------------------
  // heartbeat

  if( millis() - lastHeartbeat > heartbeatIntervall ) {
    Serial.println("Heartbeat");
    lastHeartbeat = millis();

    DPSResult a = measurePressure();
    pressureRef = a.pressure;
    tempRef     = a.temperature;
    Serial.print("Reference pressure: ");
    Serial.println(pressureRef);
    Serial.print("Reference temperature: ");
    Serial.println(tempRef/10.0);
    
    // publish heartbeat to channel 2
    dataToPublish[1] = 1;
    dataToPublish[2] = pressureRef;
    dataToPublish[3] = tempRef;
    mqttPublish( writeChannelID, writeAPIKey, fieldsToPublish, dataToPublish );

  }

  //--------------------------
  // fade in/fade out
  
  brightness = LEDS.I2CREAD(ADDRESS, READ_DIMMINGLEVEL); // Request for brightness level

  if( brightness > 0 ) {
    //Serial.println(brightness);    
    if( brightness > 4090 ) {
      brightness_decrease = true;
    }
    if( brightness < (brightness_change + 1) ) {
      brightness = 1;
      brightness_decrease = false;
    }
    if( brightness_decrease ) {
      brightness = brightness - brightness_change;
    } else {
      brightness = brightness + brightness_change;
      if( brightness > 4090 ) {
        brightness = 4095;
      }
    }
    LEDS.SetDimmingLevel(brightness);
  }

  delay(10);

  //------------------------------------------------------
  // candle effect - includes debouncing
  
  DPSResult a = measurePressure();
  if( (a.pressure - pressureRef) > 2 ) {
    pressureAboveThres = true;
  }

  if( pressureAboveThres && !lastPressureAboveThres ) {
    lastDebounceTimePressure = millis();
    lastPressureAboveThres = true;
    Serial.print("Pust .... ");
    Serial.println(a.pressure);
  }

  if(  (millis() - lastDebounceTimePressure > debouncePressureDelay) && lastPressureAboveThres ) {
    if( pressureAboveThres ) {
      if( brightness > 0 ) {
        Serial.println("Off");
        LEDS.SetDimmingLevel(0x0000);
      } else {
        Serial.println("On");
        LEDS.SetDimmingLevel(0x0FFF);
      }
    }
    pressureAboveThres     = false;
    lastPressureAboveThres = false;
  }
  
  delay(10);

}

//-------------------------------------------------------------------------------------

void mac_address() {
  
  uint8_t mac[6];
  WiFi.macAddress(mac);
  Serial.printf( "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

}

//-------------------------------------------------------------------------------------

void scan_wifi() {
  
  Serial.println("Start Wifi scan");
  int n = WiFi.scanNetworks();

  if (n == 0) {
    Serial.println("No Wifi networks found");
  } else {
    Serial.println("Networks found:");
    for (int i = 0; i < n; ++i) {

      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(") ");
      Serial.print(" [");
      Serial.print(WiFi.channel(i));
      Serial.println("] ");

      delay(10);
    }
  }

  Serial.println("Scan done");
  Serial.println("");

}

//-------------------------------------------------------------------------------------

void led_test() {

  Serial.println("LED test start");

  LEDS.SetDimmingLevel(0x0FFF); // Maximum Brightness

  LEDS.SetIntensityRGB(0x0FFF, 0x0000, 0x0000);
  delay(1000);
  LEDS.SetIntensityRGB(0x000, 0x0FFF, 0x0000);
  delay(1000); 
  LEDS.SetIntensityRGB(0x0000, 0x0000, 0x0FFF);
  delay(1000);
  LEDS.SetIntensityRGB(0x0FFF, 0x0000, 0x0000);
  delay(1000);
  LEDS.SetIntensityRGB(0x000, 0x0FFF, 0x0000);
  delay(1000); 
  LEDS.SetIntensityRGB(0x0000, 0x0000, 0x0FFF);
  delay(1000);
  LEDS.SetIntensityRGB(0x0FFF, 0x0000, 0x0000);
  delay(1000);
  LEDS.SetIntensityRGB(0x000, 0x0FFF, 0x0000);
  delay(1000); 
  LEDS.SetIntensityRGB(0x0000, 0x0000, 0x0FFF);
  delay(1000);
    
  LEDS.SetDimmingLevel(0x0000);

  Serial.println("LED test end");

}

//-------------------------------------------------------------------------------------

/**
 * Process messages received from subscribed channel via MQTT broker.
 *   topic - Subscription topic for message.
 *   payload - Field to subscribe to. Value 0 means subscribe to all fields.
 *   mesLength - Message length.
 */

int mqttSubscriptionCallback( char* topic, byte* payload, unsigned int mesLength ) {

  char p[mesLength + 1];

  memcpy( p, payload, mesLength );
  p[mesLength] = NULL;

  Serial.print( "Value: ");
  Serial.println(String(p) );

  setLEDMode( String(p).toInt() );
  
  changeFlag = 1;

}

//-------------------------------------------------------------------------------------

void mqttConnect() {

  char clientID[ 9 ];
    
  // Loop until connected.
  while ( !mqttClient.connected() ) {

    getID(clientID,8);
       
    // Connect to the MQTT broker.
    Serial.println( "Attempting MQTT connection..." );
    if ( mqttClient.connect( clientID, mqttUserName, mqttPass ) ) {
      Serial.println( "Connected with Client ID: '" + String( clientID ) + "', User '"+ String( mqttUserName ) + "', Pwd '"+String( mqttPass ) + "'");
    } else {
      Serial.println( "failed, rc = " );
      // See https://pubsubclient.knolleary.net/api.html#state for the failure code explanation.
      Serial.println( mqttClient.state() );
      Serial.println( " Will try again in 5 seconds" );
      delay(5000);
    }
  }
}

//-------------------------------------------------------------------------------------

/**
 * Build a random client ID.
 *   clientID - Character array for output
 *   idLength - Length of clientID (actual length is one character longer for NULL)
 */

void getID(char clientID[], int idLength) {

  static const char alphanum[] ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

  // Generate client ID.
  for (int i = 0; i < idLength ; i++) {
    clientID[ i ] = alphanum[ random( 51 ) ];
  }
  
  clientID[ idLength ] = '\0';
    
}

//-------------------------------------------------------------------------------------

/**
 * Subscribe to fields of a channel.
 *   subChannelID - Channel to subscribe to.
 *   field - Field to subscribe to. Value 0 means subscribe to all fields.
 *   readKey - Read API key for the subscribe channel.
 *   unSub - Set to 1 for unsubscribe.
 */
 
int mqttSubscribe( long subChannelID, int field, char* readKey, int unsubSub ){

  String myTopic;
    
  // There is no field zero, so if field 0 is sent to subscribe to, then subscribe to the whole channel feed.
  if (field == 0){
    myTopic="channels/"+String( subChannelID )+"/subscribe/json/"+String( readKey );
  } else {
    myTopic="channels/"+String( subChannelID )+"/subscribe/fields/field"+String( field )+"/"+String( readKey );
  }
    
  Serial.println( "Subscribing to " +myTopic );
  Serial.println( "State = " + String( mqttClient.state() ) );

  if ( unsubSub == 1 ){
    return mqttClient.unsubscribe(myTopic.c_str());
  }
  
  return mqttClient.subscribe( myTopic.c_str() ,0 );
    
}

//-------------------------------------------------------------------------------------

/**
 * Publish to a channel
 *   pubChannelID - Channel to publish to.
 *   pubWriteAPIKey - Write API key for the channel to publish to.
 *   dataArray - Binary array indicating which fields to publish to, starting with field 1.
 *   fieldArray - Array of values to publish, starting with field 1.
 */

void mqttPublish(long pubChannelID, char* pubWriteAPIKey, int fieldArray[], int dataArray[]) {
  
  int    index = 0;
  String dataString = "";

  while (index < 8){
    // Look at the field array to build the posting string to send to ThingSpeak.
    if ( fieldArray[index] > 0 ){
      dataString += "&field" + String( index+1 ) + "=" + String( dataArray[index] );
    }
    index++;
  }
  //Serial.println( dataString );
  
  // Create a topic string and publish data to ThingSpeak channel feed.
  String topicString ="channels/" + String( pubChannelID ) + "/publish/"+String( pubWriteAPIKey );
  Serial.println( topicString );
  mqttClient.publish( topicString.c_str(), dataString.c_str() );
  Serial.println( "Published to channel " + String( pubChannelID ) );

}

//-------------------------------------------------------------------------------------


void setLEDMode( int mode ) {

//typedef enum{
//  White, Silver, Gray, Black, Red, Maroon, Yellow, Olive, Lime, Green, Aqua, Teal, Blue, Navy, Fuchsia, Purple
//  }Colours;


  digitalWrite(BUILTIN_LED, HIGH); // LED on

  if( mode == 0 ) {
    digitalWrite(BUILTIN_LED, LOW); // LED off
    LEDS.SetDimmingLevel(0x0000);
    
  } else if( mode == 1) {
    LEDS.SetDimmingLevel(0x0FFF);
    LEDS.SetColor(Red);
    brightness_change = brightness_change_default;

  } else if( mode == 2) {
    LEDS.SetDimmingLevel(0x0FFF);
    LEDS.SetColor(Green);
    brightness_change = brightness_change_default;

  } else if( mode == 3) {
    LEDS.SetDimmingLevel(0x0FFF);
    LEDS.SetColor(Blue);
    brightness_change = brightness_change_default;

  } else if( mode == 4) {
    LEDS.SetDimmingLevel(0x0FFF);
    LEDS.SetColor(White);
    brightness_change = brightness_change_default;

  } else if( mode == 5) {
    LEDS.SetDimmingLevel(0x0FFF);
    LEDS.SetColor(Yellow);
    brightness_change = brightness_change_default;

  } else if( mode == 6) {
    LEDS.SetDimmingLevel(0x0FFF);
    LEDS.SetColor(Fuchsia);
    brightness_change = brightness_change_default;

  } else if( mode == 7) {
    brightness_change = brightness_change * 2;

  }
}

//-------------------------------------------------------------------------------------

DPSResult measurePressure() {

  float   temperature;
  float   pressure;
  int16_t oversampling = 2;
  int16_t ret;

  DPSResult a;
  a.temperature = 0;
  a.pressure    = 0;
  
  ret = Dps422PressureSensor.measureTempOnce(temperature, oversampling);

  if (ret != 0) {
    Serial.print("FAIL! ret = ");
    Serial.println(ret);
  } else {
    a.temperature = (int) (temperature * 10);
    //Serial.print("Temperature: ");
    //Serial.print(temperature);
    //Serial.println("C");
  }

  ret = Dps422PressureSensor.measurePressureOnce(pressure, oversampling);
  if (ret != 0) {
    Serial.print("FAIL! ret = ");
    Serial.println(ret);
  } else {
    a.pressure = (int)(pressure/100);
    //Serial.print("Pressure: ");
    //Serial.print((int)(pressure/100));
    //Serial.println("hP");
  }

  return a;
  
}

//-------------------------------------------------------------------------------------

void wificonnect() {

  if( WiFi.status() != WL_CONNECTED ) {

    Serial.print("connecting to ");
    Serial.print(ssid);
    WiFi.begin(ssid, password);

    int i = 0;
    while (WiFi.status() != WL_CONNECTED && i < 50) {
      delay(200);
      Serial.print(".");
      i++;
    }

    Serial.print("");

    if ( WiFi.status() == WL_CONNECTED ) {
      Serial.println("WiFi connected"); 
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());  

      Serial.print("RSSI: ");
      Serial.println(WiFi.RSSI());
    } else {
      Serial.println("Connection failed");
    }
  }

}

Credits

Infineon Team
115 projects • 189 followers

Comments