Project showcase
IoT Blink - Getting started with IoT

IoT Blink - Getting started with IoT © GPL3+

Getting started with IoT can seem scary but as with most things you can learn a great place to start is taking a look at some examples!

  • 4,006 views
  • 1 comment
  • 19 respects

Components and supplies

About this project

Anyone who's started learning about microcontrollers and code could tell you that a good place to start is by looking at the most basic example sketches provided. As often times their simplicity can teach you a lot more than you think. With the Arduino, one of my favorite examples is the blink sketch, which is deceptively short yet teaches you so much about how the Arduino IDE and Arduino boards work. So without further delay, let's take a look at an IoT version of the classic blink sketch.

Before we can jump into the IOT side of things lets just take a look at how different boards are able to blink an LED. All microcontrollers such as the Arduino, NodeMCU or Sparkfun ESP8266 Thing have pins that we can control through code and one of the most basic things we can do to these pins in make them HIGH or LOW, turn them on or off. So for example when we set a certain pin to HIGH that pin will output power (anywhere from 1 to 3 volts depending on the board) however when we then set that pin to LOW it stops outputting power almost like a digital on-off switch. Then all we have to do is add a delay between the pin going HIGH and LOW and we have a blinking LED!

Step 2: Setting Up Our Board

So there are a lot of IOT boards out there, some made by Arduino, some made by Sparkfun, some made by Adafruit and many from other places. It would be quite difficult and long to talk about each device so we've compiled some of the most popular boards however this will work on all microcontroller IOT boards.

So for this project, we will be demoing on the following boards:

  • Sparkfun ESP8266 Thing (Can be found Here)
  • NodeMCU (Can be found Here)
  • Adafruit Feather (Can be found Here)
  • Arduino (Can be found Here)

Any one of these boards will work great with this example

Step 3: Code and Libraries

To upload our code we are going to be using the very popular Arduino IDE which can be downloaded Here . Now because we are going to be using the website AppShed to control and edit the way the board works we don't need to focus on the actual code going into the board, the code we are uploading is the AppShed master sketch which allows the website to control all the pins on the board.

Now to be able to upload code to our board through the Arduino IDE we need to install its library which allows to IDE to talk to our specific board. This is done as follows:

Now we need to install the boards under board manager.

  • Navigate to Tools, then Board and then Click on Board Manager
  • Now in the search bar search for ESP8266
  • Click on the first option and click Install

Now our board is able to communicate with the Arduino IDE

Step 4: Uploading the Code

So at this point, we have downloaded the libraries that are needed to help the Arduino IDE communicate with our IoT board and we've downloaded the libraries that allow the AppShed master sketch to run, now we just need to upload the master sketch to the board.

To do this we need the following:

  • Plug your IoT board into your computer
  • Download and open the Appshed master sketch (which can be found here)
  • Navigate to tools and click on board
  • Scroll down until you see your board, then click on it (I'm using the NodeMCU so I'm going to click on NodeMCU)
  • Now navigate back to tools and click on port, from here you should see your board (should look like this "com 9")
  • Click the side facing arrow to upload and wait while it does so.

If you get a message after about 2 - 3 minutes saying done uploading then everything worked perfectly! To double-check that our board is working we can also go our WiFi setting and look for the name that we gave the board earlier if it's there it's working.

Step 5: Making the App to Control It

Now that we have the board up and running we want to be able to control the digital pins which allow us to turn the LED on and off and to do that we are going to be using the IoT side of AppShed.

The first thing we need to do is head over to appshed.com and register a free account so we can save our work. Once that's done we need to click on IoT Builder which will allow us to define the pins we want to control and then click on new IoT project.

Now I know that the built-in LED on my board is on pin 5 so I'm going to connect an LED to pin 5 in the IoT builder by clicking on the LED icon and then clicking on pin 5, however, if you have a different board you'll need to find out which pin your built-in LED is on which as easy as googling your boards name followed by built-in LED pin. Now we can just give it a name like LED and save it and we are ready to make the actual app!

So to make the app we can head back to that menu from earlier and click on appbuilder this time instead IoT builder. From here you should be presented with a simulated phone which is what we will be building our app on! The first thing to do is click the plus button at the bottom of the phone, which will take us into a new app and give us all the tools we need.

The first tool we will take advantage of is connecting the IoT board that we made to this app and we do that by clicking on boards and then we click on the board we made earlier. Now the board is linked to our app. Now we add our first button which will turn on the LED. To do this we click on the button icon under forms which will then give us to option to give it a name and actions. We start by naming it LED On then we click on the actions tab to give it an action. The action we want to give it is control of the LED pin from our IoT builder board so we click on change action and then scroll all the way to the bottom where we should find the LED action, once we've clicked on it we are then given the option to make this button set the pin as on or off, since we named the button LED on we are going to make it turn on the LED. And lastly, we just need to click save. Now we can do the same prosses for the off button and we should have a functioning barebones app that will allow us to turn on and off and LED from our phone!

Step 6: Publishing and Testing the App

At this point we have our app and IoT board ready to go, the last thing we are going to do is get our app onto our phone or anything other smart device and to do that we need to click on publish which will render the app allowing us to use it.

Let's just talk for a second about what the app is, unlike other apps you won't need to download it from the IOS or Play store and it is compatible with every single device that has a web browser this is because it is a web app that runs on your phone's browser. Which means once your app is finished publishing you can send the link to your phone by clicking share and scanning the QR code or any of the other options and the app will show up on your phone instantly.

Now if you tried clicking the on and off buttons nothing would happen because the IoT board isn't connected to your phone yet. To connect it we just need to go to your phones WiFi setting and connect to the name we gave it earlier. Now if you go back into the app you should be able to control the LEDs from your app! (if for some reason it isn't working check out the troubleshooting step)

Step 7: Taking It Further

When looking at this app and this project it does look pretty barebones but keep in mind that this can lead to much cooler projects, for example, you could connect a motor to your IoT board and control your blinds through your phone, connect a servo to the IoT board and make a phone controlled door lock or if your really skilled electronics and understand how painful and deadly it is to touch 110/220 volts you could even use a relay and an IoT board and control the lights in your room all from your phone.

Much more can be done with the app too! I spent about an hour or two trying to get my app looking really nice so I could use it in future projects and this is what I was able to come up with My App (if you're using the same IoT board as me my app should be able to control your IoT device)

So don't let the simplicity of this project hold you back!

Step 8: Troubleshooting

Of course, things don't always go as planned and that's exactly why this step is here to help sort out any issues you might have.

  • Reset you IoT device, most of the time there will be a little button on your device that resets it, hold that button down for 2 seconds and then reconnect your phone to the device.
  • Make sure your LED is on the right pin if you're using a different board to me there's a great chance that your LED isn't on pin 5 like mine is. The best thing to do is google the name of your board and do a little research to find out which pin the built-in pin is linked to
  • Make sure that your AppShed app tells you that it's downloaded and ready to be taken offline before you swap to the IoT devices WiFi

Code

Appshed master sketchC#
/*
  This a simple example of the aREST Library for the ESP8266 WiFi chip.
  See the README file for more details.

  Written in 2015 by Marco Schwartz under a GPL license.
  Modified by Torsten Stauch, Dec 2016 (v24)

  This sketch combines the functionality of running a local Access Point, 
   or using the aREST Pro service.
   The default mode is "Local AP".
   To use the "aREST Pro Mode", the device must have pins D0 and D1 bridged at startup 
   (can remain bridged if those pins not used for anything else.)

  This sketch provides additional functions to support API calls from the AppShed app.js repo
   which can be found at https://github.com/AppShed/app.js 


  v 29 - Support for L9110S Motor Driver
  v 30 - Support for Motor Shield/Base Board. Motor Pins changed D1,2,3,4
  v 31 - aREST Pro support fixed
  v 32 - Remote Control fixed
  v 33 - AP/Pro bridge D6-D7
  v 34 - AP and Pro mode simultaneously
  v 35 - no bridging, always AP and Pro
  v 36 - Support for 2 types of Motor Drivers (Motor Shield, L298N)... todo: L9110
  v 37 - NeoPixel support 
  v 38 - HashMap added
  v 39 - /info shows all pins
  v 40 - don't start NeoPixel on setup
  v 41 - Removed pin update from loop, neet to call /pins to update pins, and /info to read values
  v 42 - Removed bug in loop
  v 43 - Show MotorDriver in debug
  v 44 - Minor enhancements
  v 45 - Use ssid AppShed10 (so doesn't go online)
  v 46 - AP mode disabled, aREST cloud mode disabled - i.e. use local ip only
  v 47 - Changed Wifi to WiFi
  v 48 - Commented out neopixel, maked AP name and password easier for user to find and change

  
  --------------------------------------------------------
  NOTES
  --------------------------------------------------------

  from http://www.esp8266.com/viewtopic.php?f=40&t=6732
  Avoid using D3 with relays as it will latch on at boot and your wifi will not connect until you remove the GPIO connection from the relay.
  D8 Will also latch on and cause conflict do not use this. - See more at: http://www.esp8266.com/viewtopic.php?f=40&t=6732#sthash.IzOPRBbl.dpuf

  HASHMAP
  ref http://playground.arduino.cc/Code/HashMap


*/
// Add a name and password for your device
const char* passwordAP = "Sorry123";
char * deviceName = "PrettyFlyForAWiFi"; // change the number for every robot

// Import required libraries
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <aREST.h>
#include <Servo.h> 

// Variables to be exposed to the API
int build = 48;






// GPIO mapping
int gpio[] = {16,5,4,0,2,14,12,13,15};




// NeoPixel
/*
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(24, gpio[5], NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(24, gpio[6], NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(24, gpio[7], NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4 = Adafruit_NeoPixel(24, gpio[8], NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip = strip1;
*/



// aREST Pro key (that you can get at dashboard.arest.io)
char * key = "your_arest_key";



// Pin Values
int PinA0;
int PinD0;
int PinD1;
int PinD2;
int PinD3;
int PinD4;
int PinD5;
int PinD6;
int PinD7;
int PinD8;


// Clients
WiFiClient espClient;
PubSubClient client(espClient);

// Create aREST instance
aREST restAP = aREST();
aREST rest = aREST(client);


// Start the server
#define LISTEN_PORT           80

// Create an instance of the server
WiFiServer server(LISTEN_PORT);








// WiFi parameters
const char* ssid = "Your Wifi Name";
const char* password = "Your Wifi Password";
const char* ssidAP = deviceName;



// Functions
void callback(char* topic, byte* payload, unsigned int length);


// Variables to be exposed to the API
String analogValues = "";
String digitalValues = "";


// Declare functions to be exposed to the API
int calibrate(String command);
int commands(String command);
int logo(String command);
int runCommands(String command);
int attachServos(String command);
int setMotorDriver(String command);
int readPins(String command);

// create servo object to control a servo 
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;


// Other variables
int bridged = 0;
int enableAP = 1;
int enableCloud = 0;
int maxPinsIndex = 8;
int maxCommandQueueIndex = 19;
int maxServosIndex = 3;
int logoQueueIndex = 0;
int maxLogoQueueIndex = 20;
int motorPinsConfigured = 0;
int maxPWM = 1023;
int secondsForWiFiConnection = 9;
int wifiConnected = 0;
unsigned long previousMillisWiFi = 0; 
const long intervalWiFi = 3000;  // check to see if WiFi connected ever x milliseconds while looping
unsigned long previousMillisPro = 0; 
const long intervalPro = 500;  // x milliseconds between Pro connections
unsigned long previousMillisPinRead = 0; 
const long intervalPinRead = 500;  // x milliseconds between updating pin state



int motorDriver = 1; // default motor driver. 
int pinA1A = 1; // default pin for left motor Forward
int pinA1B = 2; // left motor backwards
int pinB1A = 3; // right motor Forward
int pinB1B = 4; // right motor Backwards
//int pinLPWM = 4; // default pin for left motor PWM
//int pinRPWM = 5; // default pin for right motor PWM
int pinPen = 5; // default pin for Logo Pen
int leftPWMF = 1023; // default PWM value for the left motor
int rightPWMF = 1023; // default PWM value for the right motor
int leftPWMB = 1023; // default PWM value for the left motor
int rightPWMB = 1023; // default PWM value for the right motor
int speedFD = 100; // default forward speed in mm/second
int speedBK = 100; // default backward speed in mm/second
int speedLT = 180; // default left rotation speed in degrees/second
int speedRT = 180; // default right rotation speed in degrees/second
int speedARCFL = 90; // default forward left arc speed in degrees/second
int speedARCFR = 90; // default forward right arc speed in degrees/second
int speedARCBL = 90; // default back left arc speed in degrees/second
int speedARCBR = 90; // default back right arc speed in degrees/second


int currentLogoCommand[2]; // [command,value,endMillis]
unsigned long currentLogoCommandExpiry; 
int commandQueue[9][19][3]; // [pin 0-19][command# 0-max][0:format 1:value 2:duration]
int commandQueueIndex[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // the current index for each pin in commandQueue
unsigned long commandTimeout[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // the time at which the command for a pin times out
int logoQueue[20][2]; // [command#] [command,value]
int servoArray[4]; // the pin numbers for the servos
unsigned long lastRandom = 0;
int hashMapLength = 50; // size of our hashMap
int hashMapIndex = 0; // next index to use 
String hashMapKeys[50]; 
String hashMapValues[50]; 



void setup(void)
{
  // Start Serial
  Serial.begin(115200);

  Serial.println("");
  Serial.println("");
  Serial.println("");
  Serial.println("----------------------------------");
  Serial.print("Build: ");
  Serial.print(build);
  Serial.print("   Device: ");
  Serial.print(deviceName);
  Serial.print("    Motor Driver: ");
  Serial.print(motorDriver);
  Serial.println("");
  Serial.println("----------------------------------");



  // make sure PWM Range is set
  analogWriteRange(maxPWM);


  // Pin 4 is the default LED OUTPUT
  pinMode(gpio[4], OUTPUT);
  digitalWrite(gpio[4],0); // 0 turns the blue LED on


  // Allocate motor pins as OUTPUT and turn off
  pinMode(gpio[pinA1A], OUTPUT);
  pinMode(gpio[pinA1B], OUTPUT);
  pinMode(gpio[pinB1A], OUTPUT);
  pinMode(gpio[pinB1B], OUTPUT);  
//  pinMode(gpio[pinLPWM], OUTPUT);
//  pinMode(gpio[pinRPWM], OUTPUT);

  digitalWrite(gpio[pinA1A],0);
  digitalWrite(gpio[pinA1B],0);
  digitalWrite(gpio[pinB1A],0);
  digitalWrite(gpio[pinB1B],0);
  
  


    // Set aREST key
    rest.setKey(key, client);
  
    // Set callback
    client.setCallback(callback);
  
    // Init variables and expose them to REST API
    rest.variable("build",&build);
    rest.variable("analogValues",&analogValues);
    rest.variable("digitalValues",&digitalValues);


    
    // Give name to device
    rest.set_name(deviceName);

      // Function to be exposed
    rest.function("calibrate",calibrate);
    rest.function("commands",commands);
    rest.function("logo",logo);
    rest.function("runCommands",runCommands);
    rest.function("attachServos",attachServos);
    rest.function("setMotorDriver",setMotorDriver);
    rest.function("readPins",readPins);

  
    // Connect to WiFi


    Serial.println("");
    Serial.println("-----------------------------");
    Serial.println("WiFi");
    Serial.println("-----------------------------");
    
    int delayMilli = 500;
    int countMilli = 0;
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      delay(delayMilli);
      Serial.print(".");
      countMilli += delayMilli;
      if(countMilli/1000 > secondsForWiFiConnection){
        break;
      }
    }

    if(WiFi.status() == WL_CONNECTED){
      wifiConnected = 1;
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.print("IP ");
      Serial.println(WiFi.localIP());
      delay(500);
    } else {
      // Make sure WiFi is disconnected
      WiFi.disconnect();
      delay(50);
      wifiConnected = 0;

      Serial.println("");
      Serial.println("*** WiFi NOT connected ***");
    }

    // Set output topic
    char* out_topic = rest.get_topic();

    


    Serial.println("");
    Serial.println("-----------------------------");
    Serial.println("Cloud Mode");
    Serial.println("-----------------------------");
    if(enableCloud == 1){
      Serial.println("Enabled");
    }else{
      Serial.println("Disabled");
    }





    
    Serial.println("");
    Serial.println("-----------------------------");
    Serial.println("Mode: Local AP");
    Serial.println("-----------------------------");



    // turn of AP mode first
    WiFi.softAPdisconnect(true);
    delay(50);

    if(enableAP == 0){
      Serial.println("AP Mode disabled");
    }      
  // Init variables and expose them to REST API
    restAP.variable("build",&build); 
    restAP.variable("analogValues",&analogValues);
    restAP.variable("digitalValues",&digitalValues);
   
  
    // Function to be exposed
    restAP.function("calibrate",calibrate);
    restAP.function("commands",commands);
    restAP.function("logo",logo);
    restAP.function("runCommands",runCommands);
    restAP.function("attachServos",attachServos);
    restAP.function("setMotorDriver",setMotorDriver);
    restAP.function("readPins",readPins);

    // Give name & ID to the device (ID should be 6 characters long)
    restAP.set_id("local");
    restAP.set_name(deviceName);


    if(enableAP == 1){
    
      // Setup AP WiFi network
      WiFi.softAP(ssidAP, passwordAP);
      Serial.println("");
      Serial.println("WiFi AP (Access Point created");
      Serial.print("SSID AP: ");
      Serial.println(ssidAP);
      Serial.print("Password: ");
      Serial.println(passwordAP);
      Serial.println("");

      // Print the IP address
      IPAddress myIP = WiFi.softAPIP();
      Serial.print("AP IP address: ");
      Serial.println(myIP);
    
    }

    // Start Web server
    server.begin();
    
    Serial.println("");
    Serial.println("-----------------------------");
    Serial.println("Web Server");
    Serial.println("-----------------------------");
    Serial.println("Started");
  

    delay(500);


    //NeoPixel
//    strip1.begin();
//    strip1.show(); // Initialize all pixels to 'off'
}








  





void loop() {

  unsigned long currentMillis = millis();



/*
 * NeoPixel Demo
  np_colorWipe(1,strip1.Color(255, 0, 0), 20); // Red
  np_colorWipe(1,strip1.Color(0, 255, 0), 20); // Green
  np_colorWipe(1,strip1.Color(0, 0, 255), 20); // Blue

  np_flash(1,strip1.Color(255, 255, 255),strip1.Color(0,0,0),20,10); 
*/


  // check if WiFi connected every so often

  if (currentMillis - previousMillisWiFi >= intervalWiFi) {
    // save the last time you checked
    previousMillisWiFi = currentMillis;

    if(wifiConnected == 1){
      if(WiFi.status() != WL_CONNECTED){
        Serial.println(WiFi.status());
        WiFi.disconnect();
        delay(50);
        wifiConnected = 0;
        Serial.println("");
        Serial.println("*** WiFi Connection lost... NOT connected ***");      
      }
    }
  }


  runLogo();
  runCommands("");


  
  
  if(enableCloud == 1){
  
    if (wifiConnected && currentMillis - previousMillisPro >= intervalPro) {
      // save the last time you checked
      previousMillisPro = currentMillis;
  
      // Connect to the cloud
      rest.handle(client);
    }  
  }


  

  // Handle REST calls
  WiFiClient clientAP = server.available();
  if (!clientAP) {
    return;
  }
  while(!clientAP.available()){
    runLogo();
    runCommands("");
    delay(1);
  }
  restAP.handle(clientAP);    
    


}







// Handles message arrived on subscribed topic(s)
void callback(char* topic, byte* payload, unsigned int length) {

  rest.handle_callback(client, topic, payload, length);

}



String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {
    0, -1  };
  int maxIndex = data.length()-1;
  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }
  String rVal = "";
  if(found>index){
    rVal = data.substring(strIndex[0], strIndex[1]);
    rVal.replace(" ","");
  }
  
  return rVal;
}





// Custom function accessible by the API
int readPins(String command) {
  // update the saved pin values for specified pins
  // command containts a comma separated list of the pins to read
  // e.g. commands = "A0,D3,D5"

  bool readAll = false;
  
  if(command == "")
    readAll = true;

  int wait = 1;

  // add a leading and trailing comma to make inspection easier
  command = ","+command+",";

  String str_Command;
  int item_counter = 0;


  while(1){
    str_Command = getValue(command, ',', item_counter++);

  
    if(!readAll && str_Command == "")
      break;

    if(readAll || str_Command == "A0"){
      PinA0 = analogRead(A0);
      delay(wait);
    }
    if(readAll || str_Command == "D0"){
      PinD0 = digitalRead(gpio[0]);
      delay(wait);
    }
    if(readAll || str_Command == "D1"){
      PinD1 = digitalRead(gpio[1]);
      delay(wait);
    }
    if(readAll || str_Command == "D2"){
      PinD2 = digitalRead(gpio[2]);
      delay(wait);
    }
    if(readAll || str_Command == "D3"){
      PinD3 = digitalRead(gpio[3]);
      delay(wait);
    }
    if(readAll || str_Command == "D4"){
      PinD4 = digitalRead(gpio[4]);
      delay(wait);
    }
    if(readAll || str_Command == "D5"){
      PinD5 = digitalRead(gpio[5]);
      delay(wait);
    }
    if(readAll || str_Command == "D6"){
      PinD6 = digitalRead(gpio[6]);
      delay(wait);
    }
    if(readAll || str_Command == "D7"){
      PinD7 = digitalRead(gpio[7]);
      delay(wait);
    }
    if(readAll || str_Command == "D8"){
      PinD8 = digitalRead(gpio[8]);
      delay(wait);
    }

    break;    

  }
  
  analogValues = String(PinA0);
  digitalValues = String(PinD0) + "," + String(PinD1) + "," + String(PinD2) + "," + String(PinD3) + "," + String(PinD4) + "," + String(PinD5) + "," + String(PinD6) + "," + String(PinD7) + "," + String(PinD8);

  return 1;
}



// Custom function accessible by the API
int commands(String command) {

  // Commands will be sent in this format:
  // format,pin,value,duration:format,pin,value,duration:....
  // format is 
  //  0-analog 
  //  1-digital
  //  101 - 199 -NeoPixel


  String str_Command;
  int item_counter = 0;

  while(1){
    str_Command = getValue(command, ':', item_counter++);
    if(str_Command == "")
      break;


    addCommandToQueue(str_Command);

  }
  return item_counter;
}





void addCommandToQueue(String command){

  // expecting command format,pin,value,duration

  String data;
  int formatInt;
  int pinInt;
  int valueInt;
  String value = "";
  int durationInt;
  
  int item_counter = 0;

  while(1){
    data = getValue(command, ',', item_counter++);
    if(data == "")
      break;
    formatInt = data.toInt();
    
    data = getValue(command, ',', item_counter++);
    if(data == "")
      break;
    pinInt = data.toInt();
    if(pinInt < 0 || pinInt > maxPinsIndex)
      break;
    
    data = getValue(command, ',', item_counter++);
    if(data == "")
      break;

    // If this format sends a string value, save it in the hashMap
    if(hasStringValue(formatInt)){
      value = data; // Also save the string value
      valueInt = getRandom(1000,2000);
      setHashValue(String(valueInt),value);


    }else{
      valueInt = data.toInt();
    }
        
    data = getValue(command, ',', item_counter++);
    // default duration is 0 (if ""), i.e. indefinite duration
    durationInt = data.toInt();

    int commandIndex = commandQueueIndex[pinInt];


    // If the queue is full, this command is lost
    if(commandIndex > maxCommandQueueIndex)
      break;
      
    commandQueue[pinInt][commandIndex][0] = formatInt;
    commandQueue[pinInt][commandIndex][1] = valueInt;
    commandQueue[pinInt][commandIndex][2] = durationInt;

    // increment the index, for the next command to use
    commandQueueIndex[pinInt]++;

    break;
  }

}


int runLogo(){

  // Run any pending Logo commands

  unsigned long currentMillis = millis();

  // Don't do anything if the current command hasn't expired
  if(currentLogoCommand[0] >= 0 && currentLogoCommandExpiry > currentMillis)
    return 1;
    
  else {
    // No current command OR Current command has expired

    // If there's a command in the queue, start it
    if(logoQueueIndex > 0){
      // save the new command details
      int new_command = logoQueue[0][0];
      int new_value = logoQueue[0][1];


      // remove the command from the Queue
      // move each command down one index (Command at 0 will be overwritten)
      for(int pos=0;pos<(logoQueueIndex-1);pos++){
        logoQueue[pos][0] = logoQueue[(pos+1)][0];
        logoQueue[pos][1] = logoQueue[(pos+1)][1];
      }
      // make sure the last one is removed (set to -1)
      logoQueue[(logoQueueIndex-1)][0] = -1;
      logoQueue[(logoQueueIndex-1)][1] = -1;
     
      // decrement the queue index
      logoQueueIndex--;
      
      // execute the new command
      executeLogo(new_command,new_value);
      
    } else{
      // No command in the queue

      // If this is an indefinite command, do nothing
      if(currentLogoCommandExpiry == 0)
        return 1;
      else if(currentLogoCommand[0] == 0)
        return 1; // current command is STOP, so don't re-execute
      else{
        // else stop the command
        executeLogo(0);      
      }
      
    }
    
  }
}


int executeLogo(int command){
  return executeLogo(command,0);
}


int executeLogo(int command, int value){

  // get the duration for this command
  int duration = getLogoDuration(command,value);
  unsigned long currentMillis = millis();

  // save the command to the currentLogoCommand
  currentLogoCommand[0] = command;
  currentLogoCommand[1] = value;
  currentLogoCommandExpiry = (currentMillis + (long)duration);
  // Special case for indefinite commands
  if(value == 0)
    currentLogoCommandExpiry = 0;


  // Make sure Motor Pins have been configured
  if(motorPinsConfigured == 0){
    initialiseMotorPins();
    pinMode(gpio[pinPen], OUTPUT);
    digitalWrite(gpio[pinPen],1); // Put the pen down by default.

  }



  // set the required pins
  // 0.   ST x (or STOP) - Stop moving for x milliseconds
  if(command == 0){
    motorLeftST();
    motorRightST();
  }

    // 1.   FD x (or FORWARD) - Move forward x millimeters, Example: FD 100
  if(command == 1){
    motorLeftFD();
    motorRightFD();
  }
    // 2.   BK x (or BACK) - Move Backward x millimeters, Example: BK 100
  if(command == 2){    
    motorLeftBK();
    motorRightBK();
  }
    // 3.   LT x (or LEFT) - Rotate the turtle x degrees left, Example: LT 45
  if(command == 3){
    motorLeftBK();
    motorRightFD();
  }
    // 4.   RT x (or RIGHT) - Rotate the turtle x degrees right, Example: RT 45
  if(command == 4){
    motorLeftFD();
    motorRightBK();
  }
    // 5.   ARCFL x Move in an arc going forward and left for x degrees, Example: ARCFL 45
  if(command == 5){
    motorLeftST();
    motorRightFD();
  }
    // 6.   ARCFR x Move in an arc going forward and right for x degrees, Example: ARCFR 45
  if(command == 6){
    motorRightST();
    motorLeftFD();
  }
    // 7.   ARCBL x Move in an arc going backward and left for x degrees, Example: ARCBL 45
  if(command == 7){
    motorLeftST();
    motorRightBK();
  }
    // 8.   ARCBR x Move in an arc going backward and right for x degrees, Example: ARCBR 45
  if(command == 8){
    motorRightST();
    motorLeftBK();
  }


  
  
    // 9.   PU (or PENUP) - Lift the Pen
  if(command == 9){
    // Pen Up. Default behaviour turns the pinPen on and off
    digitalWrite(gpio[pinPen],0);    
  }
    // 10.  PD (or PENDOWN) - Put the Pen down
  if(command == 10){
    // Pen Down. Default behaviour turns the pinPen on and off. Other Option to move servo
    digitalWrite(gpio[pinPen],1);
  }

            
  return 1;
}


void motorLeftST(){
  if(motorDriver == 1){
    analogWrite(gpio[pinA1A],0);    
    analogWrite(gpio[pinA1B],0);    
    digitalWrite(gpio[pinA1A],0);    
    digitalWrite(gpio[pinA1B],0);    

  } else if(motorDriver == 2){
    
  } else {
      analogWrite(gpio[pinA1A],0);
      digitalWrite(gpio[pinB1A],0);
  }
}

void motorRightST(){
  if(motorDriver == 1){
    analogWrite(gpio[pinB1A],0);    
    analogWrite(gpio[pinB1B],0);    
    digitalWrite(gpio[pinB1A],0);    
    digitalWrite(gpio[pinB1B],0);        
  } else if(motorDriver == 2){
    
  } else {
      analogWrite(gpio[pinA1B],0);
      digitalWrite(gpio[pinB1B],0);
  }
}

void motorLeftFD(){
  if(motorDriver == 1){
    digitalWrite(gpio[pinA1A],1);
    analogWrite(gpio[pinA1B],(maxPWM - leftPWMF));
  } else if(motorDriver == 2){
    
  } else {
    analogWrite(gpio[pinA1A],leftPWMF);
    digitalWrite(gpio[pinB1A],1);
  }
}

void motorRightFD(){
  if(motorDriver == 1){
    digitalWrite(gpio[pinB1A],1);
    analogWrite(gpio[pinB1B],(maxPWM - rightPWMF));
  } else if(motorDriver == 2){
    
  } else {
    analogWrite(gpio[pinA1B],rightPWMF);
    digitalWrite(gpio[pinB1B],1);    
  }
}


void motorLeftBK(){
  if(motorDriver == 1){
    digitalWrite(gpio[pinA1A],0);    
    analogWrite(gpio[pinA1B],leftPWMB);
  } else if(motorDriver == 2){
    
  } else {
    analogWrite(gpio[pinA1A],leftPWMF);
    digitalWrite(gpio[pinB1A],0);
  }
}

void motorRightBK(){
  if(motorDriver == 1){
    digitalWrite(gpio[pinB1A],0);    
    analogWrite(gpio[pinB1B],rightPWMB);
  } else if(motorDriver == 2){
    
  } else {
    analogWrite(gpio[pinA1B],rightPWMF);
    digitalWrite(gpio[pinB1B],0);    
  }
}

void initialiseMotorPins(){
  // Configure the motor pins as outputs
  
  // turn pin 4 off
  pinMode(gpio[pinA1A], OUTPUT);
  pinMode(gpio[pinA1B], OUTPUT);
  pinMode(gpio[pinB1A], OUTPUT);
  pinMode(gpio[pinB1B], OUTPUT);
//  pinMode(gpio[pinLPWM], OUTPUT);
//  pinMode(gpio[pinRPWM], OUTPUT);

  motorPinsConfigured = 1;
}

  

int getLogoDuration(int command, int value){
  // return the number of milliseconds for this command.

  // Special case: 0
  if(value == 0)
    return 0;

  if(command == 0)
    return value;
  if(command == 1)
    return (int)(1000.0*(float)value/(float)speedFD);
  if(command == 2)
    return (int)(1000.0*(float)value/(float)speedBK);
  if(command == 3)
    return (int)(1000.0*(float)value/(float)speedLT);
  if(command == 4)
    return (int)(1000.0*(float)value/(float)speedRT);
  if(command == 5)
    return (int)(1000.0*(float)value/(float)speedARCFL);
  if(command == 6)
    return (int)(1000.0*(float)value/(float)speedARCFR);
  if(command == 7)
    return (int)(1000.0*(float)value/(float)speedARCBL);
  if(command == 8)
    return (int)(1000.0*(float)value/(float)speedARCBR);
    
  return 0;

}


int calibrate(String command){
...

This file has been truncated, please download it to see its full contents.

Comments

Similar projects you might like

How To Use TheAmplituhedron.com To Improve IoT Projects

Project tutorial by Kutluhan Aktar

  • 1,785 views
  • 0 comments
  • 9 respects

Android App-Based Home Automation System Using IOT

Project tutorial by Team Autoshack

  • 43,269 views
  • 21 comments
  • 122 respects

Mozilla IoT WoT Gateway and ESP8266

Project tutorial by Giovanni Gentile

  • 2,768 views
  • 0 comments
  • 6 respects

IoT Thermometer Using Python

Project tutorial by Luigi Francesco Cerfeda

  • 9,884 views
  • 4 comments
  • 27 respects

KatLight - The Coolest IoT Wonderlamp

Project tutorial by remnis

  • 3,181 views
  • 4 comments
  • 11 respects
Add projectSign up / Login