Blinkit v2.5.1: Arduino integration | Slimmed down and modular code

Words
1015
Reading
5 min
Listen
Play
8y

You know those moments when you keep on implementing things and dont really look at the size of the code you are getting and suddently you see that your file size is getting too big ??

The only way to keep all the implemented features and lower file size is make it more efficient and try to make your code modular and reuse parts of it for several actions instead of coding several times for a similar action.

This is the object of this post. I have been working the last days on the backend, keeping the same features as before but more efficient !(slimming down from a 52% memory usage down to 38% on my Arduino Uno board) Which is fantastic !

Let's dive into the code !!

The following file is updated/added in the Blinkit repository

As advised previously by the moderator the commit was made directly into the main branch of Blinkit.

Files can also be found in my Github repo dedicated to Blinkit integration.

A new set of general functions for all the effects

With this release our main concern was:

  • How to keep the same features but saving some memory for future implementations ?

As per the previous release, effects where coded in each mode under each IF statement thus they were repeated several times.

In order to let the code be more efficient, modular, easier to understand and read but also smaller in size the same part of code related to a specfic effect can be made more general and handle any notification.

In fact under each IF statement for the related effect the whole code has been removed and the call for the specific function has been put instead transfering also the right parameters alongsid in order to process accordingly the trigger.

That means for example that the code triggering the rainbow effect is only written once but can handle any notification received with its relative parameters ( number of pattern repeat, speed/delay).

Below you will see how this is implemented.

What is Blinkit?

Blinkit is a notification software that can be used to give to regular and widely available devices a Steem purpose.

Supported devices:

  • USB Sticks (status light)
  • Philips HUE lamps
  • Sonoff devices
  • Arduino Boards or compatible (Genuino, etc...)
  • Camera status LED blink
  • Take photos on upvote/post/follow
  • Logitech RGB/Backlight Keyboards (new)

Blinkit can look for new Steem account Upvotes and Followers, and it can notify on new Posts made by a user.

More devices will be added in the near future.

Blinkit is free and open source, and can be downloaded from the Blinkit Github page:
https://github.com/techtek/Blinkit

For more information about the new version of Blinkit please visit the following link

COMPATIBILITY

Current release has been tested only on an Arduino UNO board. Other boards like Mega and Nano should be supported (for Nano different PWM pins should be selected, for Mega nothing to change) but have not been tested yet. Users interested in using this new feature with other boards could submit a test contribution and let us know the result of their test.

How is it implemented?

Code structure has been partially changed thus hereafter you will find the new structure of it:

  • Declaration the variables, the arrays etc
  • Initializing the setups (Serial Comunication and Output pins)
  • Listen to the COM port for incoming data or activate the standby fading function
  • Receive serial data and split it in tokens declaring the functions that will handle such data
  • Read splitted data and based on some marker store them in the right setting array
  • Wait for triggers (upvote, follower, post) over serial and based on the stored settings call the corresponding function
  • Loop the function as per the trigger

Hereafter i will show and explain only the parts of the code where changements have been made.

4) Breathing function during standby

void breath(){
   int redIntensity = 0;   //variable to handle the brightness of the RED colour of the RGB led
   int blueIntensity = 0;  //variable to handle the brightness of the BLUE colour of the RGB led
   int greenIntensity = 0; //variable to handle the brightness of the GREEN colour of the RGB led

while (Serial.available() == NULL){ //run below fading pattern till some data is detected over serial
 
 for (int i = 0; i <=255; i+=1){ //This loop will light up/dim linearly the led till it goes from off state to a value close to
                                 //R=110 G=0 B=255 the starting value for our fading pattern

    if (Serial.available() > 0){ // 
      analogWrite(RedPIN, 0);    //turn off the led when data is received and exit the loop
      analogWrite(GreenPIN, 0); //
      analogWrite(BluePIN, 0); //
      break;
      }
      
   redIntensity = i/2;
   blueIntensity = i ;
 
      analogWrite(RedPIN, redIntensity);     //
      analogWrite(GreenPIN, greenIntensity);  //activate with proper delay the led using the currently stored values for R G B
      analogWrite(BluePIN, blueIntensity);   //
      delay(10);    
      }

 for (int t = 0; t<1; t++){  //this FOR loop will let use repeat the below (whole) fade-in, fade-out pattern twice
  
   if (Serial.available() > 0){ // 
      analogWrite(RedPIN, 0);    //turn off the led when data is received and exit the loop
      analogWrite(GreenPIN, 0); //
      analogWrite(BluePIN, 0); //
      break;
      }
      
 for (int i = 127; i <=465; i+=1){    
   
   if (Serial.available() > 0){ // 
      analogWrite(RedPIN, 0);    //turn off the led when data is received and exit the loop
      analogWrite(GreenPIN, 0); //
      analogWrite(BluePIN, 0); //
      break;
      }

      /////////////////////////////////////////////////////////////////////////////////////////////
      //     first transition from R=110 G=0 B=255 (darker Violet) to R=255 G=10 B=255           //
      //   (much brighter Violet) and have chosen to use the redIntensity as the variable        //
      //part of the FOR loop based on the value of R = i we will calculate the Green brightness. //
      /////////////////////////////////////////////////////////////////////////////////////////////
      
 if(i<=255){
       redIntensity = i;
       greenIntensity = ((118937/10000)*log(i)-(559050/10000)); //The neperien logarithmic function usually wrote as ln(x) 
                                                             //is not recognized in Arduino coding by using ln but log 
    if(greenIntensity> 10){ //based on the aproximation in calculations we do this just in case not to pass the value
        greenIntensity =10;
      }
    if(greenIntensity< 1){ //based on the aproximation in the calculations this serves to not let
        greenIntensity =0;   //the Green pin turns negative 
      }
  }
  

 ////////////////////////////////////////////////////////////////////
 // linear transition between the bright Violet (R=255 G=10 B=255) //
 //       and the White colour (R=255 G=220 B=255)                 //
 ////////////////////////////////////////////////////////////////////
 
 if(i>255){ 
     redIntensity=255;
     blueIntensity=255;
     greenIntensity= i-245;
    }
       
analogWrite(RedPIN, redIntensity);     //
analogWrite(GreenPIN, greenIntensity); //activate with proper delay the led using the currently stored values for R G B
analogWrite(BluePIN, blueIntensity);   //
delay(10);                             //
}

////////////////////////////////////////////////////////////////////////
// below we reverse the loop used before to fade from Violet to White // 
//    and use it to do the other way (from White to Violet)           //
////////////////////////////////////////////////////////////////////////

for (int i = 465; i >=127; i-=1){
                                 
  if (Serial.available() > 0){ // 
      analogWrite(RedPIN, 0);    //turn off the led when data is received and exit the loop
      analogWrite(GreenPIN, 0); //
      analogWrite(BluePIN, 0); //
      break;
      }
      
 ///////////////////////////////////////////////////////////////////    
 //linear transition between the White colour (R=255 G=220 B=255) //
 //       and the bright Violet (R=255 G=10 B=255)                //
 ///////////////////////////////////////////////////////////////////
 
    if(i>255){ 
        redIntensity=255;
        blueIntensity=255;
        greenIntensity= i-245;
       }

      ///////////////////////////////////////////////////////////////////
      //       transition from R=255 G=10 B=255 to R=110 G=0 B=255     //
      ///////////////////////////////////////////////////////////////////
      
 if(i<=255){
  
       redIntensity = i;
       greenIntensity = ((118937/10000)*log(i)-(559050/10000)); 
    
    if(greenIntensity< 2){   //based on the aproximation in the calculations this serves to not let
        greenIntensity =0;   //the Green pin turns negative and let it go to zero when the loop ends
      }
  }
    
      analogWrite(RedPIN, redIntensity);     //
      analogWrite(GreenPIN, greenIntensity); //activate with proper delay the led using the currently stored values for R G B
      analogWrite(BluePIN, blueIntensity);   //
      delay(10);                             //
      }

  }


for (int i = 255; i >=0; i-=1){ //This loop will dim linearly the led till it goes totally off
                                //since we went back to R=110 G=0 B=255 with a quick calculation and a good aproximation 
                                //we set the step to take for each brightness decrease so that they get dimmed simultaneously and of the same ammount each time

   if (Serial.available() > 0){ // 
      analogWrite(RedPIN, 0);    //turn off the led when data is received and exit the loop
      analogWrite(GreenPIN, 0); //
      analogWrite(BluePIN, 0); //
      break;
      }
      
redIntensity = i/2;
blueIntensity = i ;
 
analogWrite(RedPIN, redIntensity);     //
analogWrite(GreenPIN, greenIntensity); //activate with proper delay the led using the currently stored values for R G B
analogWrite(BluePIN, blueIntensity);   //
delay(10);    
}
}
}

Compared to the previous breath() function, some of the FOR loops have been regrouped thus consumed less memory and were smaller in size of the code.

6) Wait for triggers (upvote, follower, post) over serial and based on the stored settings call the corresponding function

void setLEDon(char* data) {
  //if Arduino receives the command u from serial (upvote detected)
if (data[0] == 'u') { 
      //if ledmode is set to 3 single colour led mode      
   if(ledmode[0]==1){ 
           // if the effect selected is normal blinking
       if (EFFECT[0]== 1){ 
          blink1(RedPIN, Nofblinks[0], blinkdelay[0]);
         }
           // if the effect selected is fading effect
       if (EFFECT[0]== 2){ 
          fade1(RedPIN, Nofblinks[0], blinkdelay[0]); 
         }
      }
     // if ledmode is set to rgb led mode 
  if(ledmode[0]==2){
        // if the effect selected is normal blinking
    if (EFFECT[0]== 1){ 
        blink2(Nofblinks[0], blinkdelay[0], BRIGHTU[0], BRIGHTU[1], BRIGHTU[2]);
       }
        // if the effect selected is fading effect
    if (EFFECT[0]== 2){ 
       unsigned int P = (blinkdelay[0]*10);
       double O = 2*PI/P; 
       fade2(P, O, Nofblinks[0], BRIGHTU[0], BRIGHTU[1], BRIGHTU[2]);               
      }
        // if the effect selected is rainbow effect          
    if (EFFECT[0]== 3){ 
       rainbow( Nofblinks[0], blinkdelay[0]);
      }
       // if the effect selected is ice effect
    if (EFFECT[0]==4){ 
      ice(Nofblinks[0], blinkdelay[0]);
      }
        // if the effect selected is fire effect
    if (EFFECT[0]==5){ 
      fire(Nofblinks[0], blinkdelay[0]);
      }  
  }
 Serial.println("you got an upvote ");
 Serial.println(" "); 
}
      
//if Arduino receives the command f from serial (follower)   
if (data[0] == 'f') { 
      // if ledmode is set to 3 single colour led mode    
   if(ledmode[0]==1){  
            // if the effect selected is normal blinking  
        if (EFFECT[1]== 1){ 
           blink1(GreenPIN, Nofblinks[1], blinkdelay[1]);
          }
            // if the effect selected is fading effect
        if (EFFECT[1]== 2){ 
           fade1(GreenPIN, Nofblinks[1], blinkdelay[1]); 
          }
     }
      // if ledmode is set to 1 RGB led
   if(ledmode[0]==2){ 
           // if the effect selected is normal blinking
       if (EFFECT[1]== 1){ 
           blink2(Nofblinks[1], blinkdelay[1], BRIGHTF[0], BRIGHTF[1], BRIGHTF[2]);
          }
           // if the effect selected is fading effect
       if (EFFECT[1]== 2){ 
          unsigned int P = (blinkdelay[1]*10);
          double O = 2*PI/P; 
          fade2(P, O, Nofblinks[1], BRIGHTF[0], BRIGHTF[1], BRIGHTF[2]);             
          }
           // if the effect selected is rainbow effect
       if (EFFECT[1]== 3){ 
          rainbow(Nofblinks[1], blinkdelay[1]);
          }
           // if the effect selected is ice effect
       if (EFFECT[1]==4){ 
          ice(Nofblinks[1], blinkdelay[1]);
          }
           // if the effect selected is fire effect
       if (EFFECT[1]==5){ 
          fire(Nofblinks[1], blinkdelay[1]);
         }  
  }
 Serial.println("you got a new follower ");
 Serial.println(" "); 
}
     
  
   //if Arduino receives the command p from serial (new post) 
if (data[0] == 'p') { 
       // if ledmode is set to 3x single led mode
    if(ledmode[0]==1){  
             // if the effect selected is normal blinking  
         if (EFFECT[2]== 1){ 
            blink1(BluePIN, Nofblinks[2], blinkdelay[2]);
            }
             // if the effect selected is fading effect
         if (EFFECT[2]== 2){ 
            fade1(BluePIN, Nofblinks[2], blinkdelay[2]);  
            }
        }
       //if ledmode is set to RGB led mode 
    if(ledmode[0]==2){
             // if the effect selected is normal blinking
         if (EFFECT[2]== 1){ 
             blink2(Nofblinks[2], blinkdelay[2], BRIGHTP[0], BRIGHTP[1], BRIGHTP[2]);
            }
             // if the effect selected is fading effect
         if (EFFECT[2]== 2){ 
             unsigned int P = (blinkdelay[2]*10);
             double O = 2*PI/P; 
             fade2(P, O, Nofblinks[2], BRIGHTP[0], BRIGHTP[1], BRIGHTP[2]);                 
            }
             // if the effect selected is rainbow effect
         if (EFFECT[2]== 3){ 
             rainbow( Nofblinks[2], blinkdelay[2]);
            }
             // if the effect selected is ice effect
         if (EFFECT[2]==4){ 
            ice(Nofblinks[2], blinkdelay[2]);
           }
           // if the effect selected is fire effect
        if (EFFECT[2]==5){ 
            fire(Nofblinks[2], blinkdelay[2]);
           }
           
      Serial.println("there is a new post ");
      Serial.println(" "); 
     } 
  }
}

As you can see, this part of the code has been slimmed down very much. Now, instead of coding directly the effect after each if (EFFECT[...]) now after each IF statement there is the call for the corresponding function that will receive the parameters with which to do the trigger.

For example:

if rgb mode is set and for the upvote notification the fire effect was chosen (as below),

if (EFFECT[0]==5){ 
            fire(Nofblinks[0], blinkdelay[0]);
           }

the function called fire will get triggered and will use Nofblinks[0] and blinkdelay[0] as parameters for the trigger.

The complete Arduino sketch file (.INO) and all the related information can be downloaded from the Blinkit Github repo link.

Loop the function as per the trigger

void fire(int Nblink, int LEDdelay){
  
 for (int a= 0; a< Nblink; a++){ //repeat the rainbow effect as per the Nofblinks[1] value
     for (int y=0; y<=295; y++){
           if (Serial.available() > 0){ // 
                 analogWrite(RedPIN, 0);    //turn off the led when data is received and exit the loop
                 analogWrite(GreenPIN, 0); //
                 analogWrite(BluePIN, 0); //
                 break;
               }
          // fade in till full red brightness
       if(y<=255){
          analogWrite(RedPIN, y);
         }
          // fade to orange-yellow
       if(y>=255){
          analogWrite(GreenPIN, (y-255));
         }
          delay ((LEDdelay/20));  
    }

    for (int x=295; x>=0; x--){
           if (Serial.available() > 0){ // 
                 analogWrite(RedPIN, 0);    //turn off the led when data is received and exit the loop
                 analogWrite(GreenPIN, 0); //
                 analogWrite(BluePIN, 0); //
                 break;
               }
          // fade back to red
       if(x>=255){
          analogWrite(GreenPIN, (x-255));
         }
          // fade till off
       if(x<=255){
          analogWrite(RedPIN, x);
         }     
      delay ((LEDdelay/20));  
    }
 }
     analogWrite(RedPIN, 0); // turn off the led
     analogWrite(GreenPIN, 0); // (just to make sure)
}

As per above example, you can see that the effect has been coded using general variables names that are getting their value directly through the call for the function thus triggering the function to do, in this case, the fire effect.

In order to be able to run Arduino with Blinkit, it is a must (as per the current initial release) to firstly upload the sketch using the official Arduino IDE software. techtek@techtek and I (electronicsworld@electronicsworld) are working on making it possible to upload sketch directly to Arduino boards/Arduino compatible boards through Blinkit by using some supported features of Arduino IDE software.

The Wiring Diagram

Wiring diagram for both ledmode is the same and can be found in Blinkit repo or in my repo.

Technical Support

Technical support is available, if you may encounter a problem, or if you want to know if your device is supported or will be supported in the near future.

How to contribute?

Do you have a question, or suggestion about the integration of Arduino in Blinkit ? Feel free to contact me on Discord (eliaraysalem#0829) or leave a comment below.