Arduino blog

Arduino blog

Arduino thinkering

This blog is about things I come by related to Arduino which I feel are inspiring/important/funny enough to write about.

Controlling Arduino over the web: Blinking a led the cool way. Part 2:blinkled

Arduino sketch experiancesPosted by Jan Sat, January 10, 2015 19:19:04
Preface:

If you have not yet read this blog post Controlling Arduino over the web: Blinking a led the cool way. Part 1:SerialStringReader please read it first.

What you will learn in this post:

In the previous post I discussed the SerialStringReader to read line by line from the serial port.
In this post we add my blinkled library to make a led blink based on serial input.
The point of this post is to get a better understanding of the way I Use classes with setup() and loop().

I consider this a low slope learning curve. The next one will be steep.

Lets get started:


Yes blinking a led is cool. But controlling the on/off rate is cooler. You can do this with 2 potentiometers (one to control the off time one to control the on time) .....but we want to get to web control. Controlling a potentiometer over the web is not exactly easy. We need another way in.

Controlling over the serial port is more ready for the web. Therefore in this example we will use the SerialStringReader to control blinkled directly.

We will use "fixed line commands" to control the blinking of a led.

Note that the code is purely for learning purposes and in no way my advised way.



So here is the code

#include "SerialStringReader.h"

#include "BlinkLed.h"

//for the stream you want to read info from you need to declare a SerialStringReader

//you can only have one

SerialStringReader myCommunicator;



//Define that the USB serial (pin 0 and 1 on the uno) is to be used by the mySerialReader

//If you want to use the yun with the bridge use Serial1

#define THESERIAL Serial

Stream &SerialInput = THESERIAL;

Stream &SerialOutput = THESERIAL;



BlinkLed led13(13,500,2000);

//The setup function is called once at startup of the sketch

void setup()

{

delay(2000);

THESERIAL.begin(115200);

SerialOutput.println("serialStringReaderDemo2");

led13.setup();

myCommunicator.setup();

}

// The loop function is called in an endless loop

void loop()

{

myCommunicator.loop();

led13.loop();

if (myCommunicator.messageReceived())

{

SerialOutput.println("You have send a message to Arduino.");

SerialOutput.println("And the message is:");

char * message=myCommunicator.getMessage();

SerialOutput.println(message);

if (strcasecmp(message,"LED SLOW")==0)

{

led13.setOnInterval(5000);

led13.setOffInterval(5000);

SerialOutput.println("changed to slow");

}

if (strcasecmp(message,"LED FAST")==0)

{

led13.setOnInterval(100);

led13.setOffInterval(100);

SerialOutput.println("changed to fast");

}

if (strcasecmp(message,"LED ASYNC")==0)

{

led13.setOnInterval(1000);

led13.setOffInterval(200);

SerialOutput.println("changed to async");

}

}

}
Before you can build it you need to download the latest version of the lib at https://github.com/jantje/libraries/tree/master/BlinkLed

What as changed from the previous demo?

I included blinkled.h and I declared

BlinkLed led13(13,500,2000);

The 3 parameters are the led pin the on interval and the off interval. In other words the led on a arduino connected to pin 13 will be on for 500 mS and then off for 2000mS if you call led13.setup(); in setup and led13.loop(); in loop()

Adding led13.setup(); to setup about covers the changes in setup()

Now lets have a look at loop.

Loop() starts with the expected

myCommunicator.loop();
led13.loop();

Next to that I added a switch case. Unfortunately C/C++ does not support switch cases with strings so I had to implement the switch case with if statements.

The code tests for any of these strings "LED SLOW", "LED FAST" and "LED ASYNC".

If one of these lines of comments arrive I change the blinking rate of the led by stetting the on and off interval.

What is in blinkled.

Lets first take a look at the constructor.

BlinkLed::BlinkLed(uint8_t ledPin,uint32_t onInterval ,uint32_t offInterval )

{

myLedPin = ledPin; // the number of the LED pin

myLedState = LOW; // ledState used to set the LED

myPreviousMillis = millis(); // will store last time LED was updated

myOnInterval = onInterval;

myOffInterval=offInterval;

}

As you can see nothing really exiting.

Now lets look at the set on and off interval

void setOnInterval(uint32_t onInterval){myOnInterval=onInterval;};

void setOffInterval(uint32_t offInterval){myOffInterval=offInterval;};

As you can see I only set the values I do not act upon the change.

This is a very important rule for me. Only the loop() can do calculations and changes.

This approach has a lot of benefits such as:

1. If a loop takes long it can only be because of some code in the class itself.

2. The sequence of changing values is completely irrelevant. Whether you change on first and then off is of no importance as only loop will do actual changes and at that point in time both have been changed.

3. The only object that can have changed state during your loop call is the object itself. As such the loop call can consider itself as “in a stable environment”. This seriously reduces the complexity of the code. Compare it to a board game where typically each player does its move one after the other. Not having this rule makes it comparable to a multiplayer on-line game.

4. Because of these rules the re-usability of the classes has increased.

Draw backs of this approach:

Even though the loop has to accommodate for all actions it still has to be fast. Assume your loop takes 10ms to finish and you have 10 objects that means 100ms for each and every cycle in the main loop to finish. I think that is way to long. In other words: DO NOT USE DELAY() -I guess you have heard this before smiley -

And now loop()

void BlinkLed::loop()

{

// here is where you'd put code that needs to be running all the time.

// check to see if it's time to blink the LED; that is, if the

// difference between the current time and last time you blinked

// the LED is bigger than the interval at which you want to

// blink the LED.

uint32_t myInterval =myOnInterval;

if (myLedState == LOW)

{

myInterval =myOffInterval;

}


unsigned long currentMillis = millis();

if(currentMillis - myPreviousMillis > myInterval) {

// save the last time you blinked the LED

myPreviousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:

if (myLedState == LOW)

{

myLedState = HIGH;

}

else

{

myLedState = LOW;

}

// set the LED with the ledState of the variable:

digitalWrite(myLedPin, myLedState);

}

}

This is basically blink without delay.

Whats up next?

Now that the setup(), loop(), blinkled and serialstringreader are fully understood it is time to explain a generic way to change attributes and variables over the serial port.

Please post a comment if you want that post to be written.



  • Comments(0)//blog.baeyens.it/#post17