element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Blog [Dynamic Living-Room Lights] The Tree Code explained - Write a protocol with interrupts.
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: ipv1
  • Date Created: 24 Jan 2015 4:01 AM Date Created
  • Views 548 views
  • Likes 1 like
  • Comments 0 comments
  • iot_holidaylights
  • ip_iot
  • code
  • holiday_mood
  • serial
  • arduino
Related
Recommended

[Dynamic Living-Room Lights] The Tree Code explained - Write a protocol with interrupts.

ipv1
ipv1
24 Jan 2015

  • Link to previous posts
  • Preface
  • The problem
  • The Approach
  • The communications code
  • The protocol
  • The Loop
  • Conclusion

Link to previous posts

  • [Dynamic Living-room Lights] Description
  • [Dynamic Living-room Lights] Simple System Design
  • [Dynamic Living-Room Lights] The YUN review - When the Penguin Met The Arduino.
  • [Dynamic Living-Room Lights] The Infineon RGB LED Shield Review
  • [Dynamic Living-Room Lights] The Infineon RGB LED Shield -Library!
  • [Dynamic Living-Room Lights] The Lights Teaser Video
  • [Dynamic Living-room Lights] The YUN talks to OpenHAB
  • [Dynamic Living-room Lights] Building the Mood Lights
  • [Dynamic Living Room Lights] The XMAS Tree
  • [Dynamic Living-Room Lights] IoT Holiday Lights Minions
  • [Dynamic Living-Room Lights] The Big Picture - The Final Build
  • [Dynamic Living-Room Lights] Paho For Python - Writing better code

 

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. image 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

  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube