Link to previous posts

 

Preface

 

My project for the Internet of Holoday lights was based around our living room which was not very livable. It was a mess and with the upcoming holidays I wanted to set the living room in such a way that it would be suitable for entertaining guests. Additionally I wanted to accomplish the above mentioned in such a way that the holiday lighting becomes part of the living room and I don't need to remove it after the holidays. Hence the concept of Dynamic Living-room Lighting.

 

In the previous posts, I have review the YUN and the infineon shield and have presented an overview of the project system. I also setup the place for the lighting with some homemade arts and crafts and give a preview of the system setup. I explained the Library I made for the Infineon Shield as well as the implementation for the MoodLights and made them Dynamic. I also made a XMAS Tree with LEDs and some stuff. I connected them to the YUN and made the control for the Xmas Tree Dynamic and static. It is now integrated into the OpenHAB interface and the YUN works as a relay. I have made the minions dance using a DIY approach and connected them to an RPi. I also wrote a python script to get mentions on twitter and play music while controlling the minions. I also showed you the final build but not yet a video. post, I go back to the minions and make them learn MQTT.

 

In this post while I wait for my video to upload, I explain the code for the tree

 

The problem

 

The basic issue that I was facing is the ability to connect two pieces of my project which is the YUN and the Tree together. I initially though of using a wireless route but in the end, since I needed to send a direct audio line to the tree anyways, hence I chose to use the wired approach and an old school way of doing things on it. There are a couple of methods of doing what I am doing like libraries and stuff and any suggestions are welcome.

 

The Approach

 

My approach was to build in two steps.

Step 1. Build the communication

Step 2. Build the activity functions around the communication.

I will briefly explain the code for both in the next few sections.

 

The communications code

I built the communications part on top of the serial interface of the arduino. I generally use the interrupts system in any microcontroller since it makes sure I 'don't wanna miss a thinngg'(-Aerosmith). Sorry about that pun.

Anyways I start with the example code on the arduino and I use the Serial Event example

 

String inputString = "";        // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete







void setup() {
  // initialize serial:
  Serial.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
}


void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {
    Serial.println(inputString);
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
}


/*
  SerialEvent occurs whenever a new data comes in the
hardware serial RX.  This routine is run between each
time loop() runs, so using delay inside loop can delay
response.  Multiple bytes of data may be available.
*/
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}






Here you can see that there is a function called serialEvent() which executes automatically every time the arduino receives a character. There are two global variables that can be accessed from anywhere in the arduino program where we save the received string and a notification flag that a string was completely received. BUT I don't need that so I start by deleting way the code in the functions and write my own.

 

The serialEvent is supposed to be triggered everytime I get a single byte over the UART and hence the code becomes something like...

 

void serialEvent() {
  while (Serial.available()) {
      // Read a char
      char inChar = (char)Serial.read();
      if(inChar==':'){                        // Start New Frame
          memset(ptr, 0, FRAMESIZE);
          inFrame=true;
          myIndex=0;
      }
      if(inFrame==true  && myIndex<FRAMESIZE){ // Add a byte
            *(ptr+myIndex)=inChar;
            myIndex++;
      }
      if(myIndex==FRAMESIZE){
          inFrame=false;
          if(inChar=='#')
            memcpy(&myFrame, ptr, FRAMESIZE);
      }
  }
}






 

In my code, I have a global flag inFrame which tells me if I am in between frame receives. The reason why I have it as a global and not a static is because I later want to implement a timer and a time out which means that if it takes too long to receive a complete frame then prolly something is wrong and I need to discard the data because something went wrong.

In this code I simply wait for ':' which is my start of frame and then use memset to initialize the space with 0s and set some flags. In the next iteration, the function will be 'inFrame' and hence it will copy the data to the memory. I understand pointers so I just use that instead of the dozen other methods. I also check for my maxFrameSize since my protocol has a fixed frame size. I can use a variable frame size too but maybe some other day.

In the end if the received data matches the frame size, we check for the endofframe which is a '#'. Everything in between can be a ascii character or anthing else but our code does not care about that. The question is what is that pointer pointing to?

 

The protocol

 

I made a structure for my protocol and it's quite simple.

struct sFrame{
    char cStart; // Expect :
    char cMode;  // A-Audio, M-Manual with RGB, P-Pattern
    char cRed;
    char cGreen;
    char cBlue;
    char cEnd;
};

As you can see that there are char type variables for everything. These can be replaced but again not our motive right now. In the global space, I do the following.

 

struct sFrame myFrame, buffer;            // Object to store the frame
char *ptr = (char*)&buffer;      // Point to the object

 

This creates an object without using the heap (malloc) since I will need a fixed size throughout the lifetime of my system. Next I create a pointer to this buffer BUT cast it into a char type. This makes sure when I ptr++, I jump to the next char in my structure. Easy! But how do I use this?

 

The Loop

 

The code for the loop is given below.

 

void loop() {
  // print the string when a newline arrives:


  if(myFrame.cMode=='A'){
      //Serial.println("Audio Mode");
      hue0 = constrain(map(analogRead(channel), 0, 400, 0, 255), 0, 255);  // Read Audio
      uint32_t color0 = Wheel(hue0);
      //Shift the current values.
      for (i = 0; i<NUMPIXELS; i++){
          data_array[i+1] = data_array[i];
      }
      data_array[0] = color0;
      for(i=0; i<NUMPIXELS; i++){
          pixels.setPixelColor(i, data_array[i]);
          pixels.show(); // This sends the updated pixel color to the hardware.
      }
  }else if(myFrame.cMode=='M'){ // Manual mode
        for(i=0; i<NUMPIXELS; i++){
          pixels.setPixelColor(i, pixels.Color(myFrame.cGreen, myFrame.cRed, myFrame.cBlue));
          pixels.show(); // This sends the updated pixel color to the hardware.
      }
  }else if(myFrame.cMode=='P' && myFrame.cRed==0x00){
        rainbowCycle(20);
  }else if(myFrame.cMode=='P' && myFrame.cRed==0x01){
        colorWipe(pixels.Color(240, 0, 0), 200); // Red
        colorWipe(pixels.Color(0, 240, 0), 200); // Green
        colorWipe(pixels.Color(0, 0, 240), 200); // Blue
        colorWipe(pixels.Color(240, 240, 0), 200); // Red
        colorWipe(pixels.Color(0, 240, 240), 200); // Green
        colorWipe(pixels.Color(240, 0, 240), 200); // Blue
  }
}

 

In this example, I use the functions from Adafruit's NeoPixel Library to implement the patterns. When in the loop, I check for the mode settings. If its A then so something and if M then do something and if P then do something else. The serial interrupt takes care of serial communication in the background. Since I have created simple objects for the structure hence I can access the member functions with the . operator. Nothing to it.

 

Conclusion

I wanted to write a short article to explain the working of asynchronous events on a microcontroller and here it is. This is the simplest possible implementation and you can expand it as you like. There is no library code size since there is no library and I hope you got something while reading this. Any suggestions are most welcome and I if you do a project and use any snippet, just say Hi in the comments.

 

 

Thanks,

IP