Using Blynk to Manage Sensor Data and Motor Control

I am particularly new to the community of posting my work so please bare with me. I am trying to use Blynk to facilitate the photocell and thermocouple data that my arduino Mega is interpreting. I have not debugged the motor part of the program so that and some other portions of the code that I am not currently working on are commented out. The main issue that I would like to address is the photocell. I can get it to output the correct data to the serial monitor and even to Blynk (only when it is sending to the virtual pin within the loop() function) but once I try to send the data through the void sendUptime() function I do not get an output on the display app-side.

What is interesting is that the temperature data sends just fine so I can not figure out the difference between the two. Any help on this matter will be appreciated.

I am using an arduino mega 2560 and the arduino wifi shield 101 for this project.

#include <Wire.h>
#include <Adafruit_MotorShield.h>
//#include "utility/Adafruit_MS_PWMServoDriver.h" // may not need this library (will have to test)
#include <Time.h>

#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <SPI.h>
#include <WiFi101.h>  // adruino wifi shield 
#include <BlynkSimpleWiFiShield101.h>
#include <SimpleTimer.h>

// Auth Token provided in the Blynk App.
char auth[] = ""; //uno

SimpleTimer timer;

// Your WiFi credentials
char ssid[] = "";
char pass[] = "";                // Set to "" for open networks

//byte state0 = 0;
//byte state1 = 0;               // states for motor control and awareness

// Pin declarations & critical variable definitions
const byte tempPin = 62;         // input pin A8 (89) for temp sensor
const byte photoPin = 63;        // input pin A9 for photocell sensor
const byte LEDR = 22;             // Digital pin 22
const byte LEDG = 23;             // Digital pin 23
const byte LEDY = 24;             // Digital pin 24
const byte LEDB = 25;             // Digital pin 25
const byte LEDW = 26;             // Digital pin 26
const byte reedSwPin = 27;        // Digital pin 27
const byte stepsForRev = 200;        // # steps for one revolution 
const byte maxRev = 69;             // max # of revolutions to open or close shades
byte numRevFwd = 0;                // counter for #revolutions forward
byte numRevBack = maxRev;         // counter for #revolutions backward

// photo sensor and thermo sensor initialization
int photoRead = 0;
int thermoRead = 0;
float thermoVoltage = 0;
float tempC = 0;
float tempF = 0;

// Definitions for the data revieved by buttons
int overUp = 0;
int overDown = 0;
int timeReg = 0;
int selfReg = 0;

// Create motor shield obj w/ default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
Adafruit_StepperMotor *myMotor = AFMS.getStepper(stepsForRev, 2); // 200 step/rev (1.8 degree) motor connected ot M3&M4

void sendUptime()
{
   Blynk.virtualWrite(V5, millis() / 1000);

   Blynk.virtualWrite(V0, tempC);
   Blynk.virtualWrite(V1, tempF);
   Blynk.virtualWrite(V2, photoRead);
}

void setup() {
  Serial.begin(9600);
  
  // Setup function to be called every second
  timer.setInterval(1000L, sendUptime);
  
  Blynk.begin(auth, ssid, pass);  // setting-up the blynk app

  while(Blynk.connect() == false){
    // will wait until connected
  }

  AFMS.begin();                // create with the default frequency 1.6KHz
  myMotor->setSpeed(69);      // set the speed in rpms
  //delay(1000);               // allowing time for transients to die down

  pinMode(LEDR, OUTPUT);        // Red
  pinMode(LEDG, OUTPUT);       // Green
  pinMode(LEDY, OUTPUT);      // Yellow
  pinMode(LEDB, OUTPUT);     // Blue
  pinMode(LEDW, OUTPUT);    // White
  //pinMode(IRpin, INPUT);   // for infrared remote (may not need if app can get working)

  //setting LEDs to default off or LOW
  digitalWrite(LEDR, LOW);    
  digitalWrite(LEDG, LOW);    
  digitalWrite(LEDY, LOW);
  digitalWrite(LEDB, LOW);
  digitalWrite(LEDW, LOW);

  // The following is to initialize the position of the shades
  Serial.println("Begin Shade Position Initialization");
  pinMode(reedSwPin, INPUT);
  int StatoSwitch = 0;
  /*
   while (StatoSwitch == LOW)
  { 
    delay(100); // may need to increase the delay   
    StatoSwitch = digitalRead(reedSwPin);
    if (StatoSwitch == HIGH){
        break;}
    else{
        myMotor->step(stepsForRev, BACKWARD, SINGLE);}
  }
  */
  Serial.println("End SetUp");
}// end setup()
/*
// Flag not to be re-sync on every reconnection
bool isFirstConnect = true;
BLYNK_CONNECTED()
{
    Serial.println("Begin isFirstConnected");
    if (isFirstConnect){
      //will request Blynk server to re-send latest values for all pins
      Blynk.syncAll(); 
      isFirstConnect = false;    // since not fist connect annymore
    }
    Serial.println("End isFirstConnected");
}
*/
/*
// setting Virtual Pins 6 - 9 for the pushbuttons to get data (1 or 0)
 BLYNK_WRITE(V6)
 {
   int overUp = param.asInt();
 }
BLYNK_WRITE(V7)
{
  int overDown = param.asInt();
}
BLYNK_WRITE(V8)
{
  int timeReg = param.asInt();
}
BLYNK_WRITE(V9)
{
  int selfReg = param.asInt();
}
*/
void loop() {
    Blynk.run();    // running the Blynk app
    timer.run();    // initiates SimpleTimer
    sensorData();
    //stepper();
}// end loop()

/*
char buttonCND()  // form-fitted from infared to phone app buttons
{
  // 1 should be if a button is switched on
  if (overUp == 1)              // up
    return 'A';
  else if (overDown == 1)       // down
    return 'B';
  else if (timeReg == 1)        //day regulation mode
    return 'C';
  else if (selfReg == 1)        // self regulation
    return 'D';
}

void stepper()
{
  //Serial.println("Begin Stepper");
  char state = buttonCND();

  switch(state){
    case 'A':  // override condition for open
    {
      Serial.println("Begin CaseA");
      digitalWrite(LEDR, HIGH);
      digitalWrite(LEDG, LOW);
      digitalWrite(LEDY, LOW);
      digitalWrite(LEDB, HIGH);
      digitalWrite(LEDW, LOW);
      
      while(numRevBack != maxRev)
      {
        myMotor->step(stepsForRev, BACKWARD, SINGLE);
        numRevFwd--;
        numRevBack++;
      }
      //LED green to indicate function complete
      GREEN();
    }
    
    case 'B': //override condition for close
    {
      Serial.println("Begin CaseB");
      //LED blue to indicate override
      //LED red to indicate motor moving
      digitalWrite(LEDR, HIGH);
      digitalWrite(LEDG, LOW);
      digitalWrite(LEDY, LOW);
      digitalWrite(LEDB, HIGH);
      digitalWrite(LEDW, LOW);
      
      while(numRevFwd != maxRev)
      {
        myMotor->step(stepsForRev, FORWARD, SINGLE);
        numRevFwd++;
        numRevBack--;
      }
      GREEN();
    }
    
    case 'C':  // Regulation for time (morning and night)
    {
      Serial.println("Begin CaseC");
      //LED yellow to indicate time regulation mode
      digitalWrite(LEDR, LOW);
      digitalWrite(LEDG, LOW);
      digitalWrite(LEDY, HIGH);
      digitalWrite(LEDB, LOW);
      digitalWrite(LEDW, LOW);
 
        if (photoRead > 200) //Daytime
        {
          //LED red to indicate motor moving
          RED();
          while(numRevBack != maxRev)
          {
            myMotor->step(stepsForRev, BACKWARD, SINGLE);
            numRevFwd--;
            numRevBack++;          
          }
          //LED green to indicate function complete
          GREEN();
        }
        
        else //Nighttime
        {
          //LED red to indicate motor moving
          RED();
          while(numRevFwd != maxRev)
          {
            myMotor->step(stepsForRev, FORWARD, SINGLE);
            numRevFwd++;
            numRevBack--;
          }
          //LED green to indicate function complete
          GREEN();
        }
        
    }
    
    case 'D': // self-regulation state
    {
      Serial.println("Begin CaseD");
      //LED white to indicate self-regulating mode
      WHITE();  
      
      if (tempF >= 75)
      {
        //close all the way
      }

      else if (tempF < 75 || tempF >= 70)
      {
        //close to 2/3 closed
      }

      else if (tempF < 70 || tempF > 65)
      {
        //close to 1/3
      }

      //LED red to indicate motor moving
      //Turn off all other LEDS
      GREEN();
    }
  }
} // end stepper()
*/

void sensorData()
{
      analogRead(tempPin);        
      //delay(10);                 
      thermoRead = analogRead(tempPin);         // read from temp sensor
      thermoVoltage = thermoRead * 5.0;
      thermoVoltage /= 1024.0;
      tempC = (thermoVoltage - 0.5) * 100;      // converting to celcius
      tempF = (tempC * 9.0 / 5.0) + 32.0;
      
      analogRead(photoPin);
      //delay(10);
      int photoRead = analogRead(photoPin);     // reads photocell
      //delay(10);
      
  /*  This bit is for debugging the sensors
   Serial.print(tempC); Serial.println(" degrees C");
   Serial.print(tempF); Serial.println(" degrees F");

  //photocell
  Serial.print("Analog reading of light is: ");
  Serial.print(photoRead);
  // threshholds for determining light intensity from photocell
   if (photoRead < 10) {
    Serial.println(" - Dark");
  } else if (photoRead < 200) {
    Serial.println(" - Dim");
  } else if (photoRead < 500) {
    Serial.println(" - Light");
  } else if (photoRead < 800) {
    Serial.println(" - Bright");
  } else {
    Serial.println(" - Very bright");
  }
  */
} 

void RED()
{
    digitalWrite(LEDR, HIGH);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDY, LOW);
    digitalWrite(LEDB, LOW);
    digitalWrite(LEDW, LOW);
}

void GREEN()
{
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDG, HIGH);
    digitalWrite(LEDY, LOW);
    digitalWrite(LEDB, LOW);
    digitalWrite(LEDW, LOW);
}

void YELLOW()
{
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDY, HIGH);
    digitalWrite(LEDB, LOW);
    digitalWrite(LEDW, LOW);
}

void BLUE()
{
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDY, LOW);
    digitalWrite(LEDB, HIGH);
    digitalWrite(LEDW, LOW);
}

void WHITE()
{
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDY, LOW);
    digitalWrite(LEDB, LOW);
    digitalWrite(LEDW, HIGH);
}

IN 99% of cases motor control requires Real Time application, which is not what you are doing as you don’t have control over execution of your commands in real time. You should think about it and use FreeRTOS or any other Real Time OS, why? Because you want to have predictable results and you want your application to be safe.

As for your problem you should perhaps give output fro Blynk Debug

Hello, thank you for your reply! I will certainly look into that in the next phase of integration regarding the real time application of the motor. For the Blynk Debug however, I am not sure what it is you mean exactly. Can you elaborate a little more, sorry?

At the very beginning of the file add:

#define BLYNK_PRINT Serial
#define BLYNK_DEBUG

then look at Serial output.

OK, I added that line of code to the top. I am not too sure how to interpret the information but I can see a line saying <vw531 appearing in different variations. Is it safe to assume that the numbers after the <vw are what is being sent to the app via virtual pins?

Sorry for some reason the rest of the post did not transfer. The line that I am seeing in the Serial Monitor is: <vw531 is it safe to assume that the number after the vw is what is being sent to the Blynk display?

yep exactly it would be good if you modify your sendUptime() like so:

void sendUptime()
{
   Serial.println("Send Uptime started");
   Blynk.virtualWrite(V5, millis() / 1000);
   Blynk.virtualWrite(V0, tempC);
   Blynk.virtualWrite(V1, tempF);
   Blynk.virtualWrite(V2, photoRead); 
   Serial.println("Send Uptime finished");
}

than you should basically see 4 variables sent in serial monitor

Ok cool, that makes much easier to read thanks. I will also make the assumption that the first number after the <vw is the virtual pin that I am working with. If that is the case I am sending data with all of the other vPINS excepts whichever one I have attached to the photoRead variable are sending appropriately. The photoRead vPIN is sending 0’s with no change.

ok I found mistake in your code, in sensorData() you have overloaded photoRead variable by doing like so:

int photoRead = analogRead(photoPin); // reads photocell

it should be:

photoRead = analogRead(photoPin); // reads photocell

Hahaha thank you very much. I probably would not have seen that for a while longer. If nothing else I have now picked up some valuable debugging practices for using this application.

No problem here. Debugging is hard on Arduino because there is no proper debuging interface in most cases. Although mega should have JTAG interface.

Ok, I did some research on that. It looks very useful Ill have to defiantly look into implementing that. By the way, do you know of any reason that I am getting fluctuations in the data that is being sent? I have a feeling it has to do with fluctuations by the sensors themselves. I think the delay(10) were mitigating that but as the app calls for no delays I am not sure how to get around that.

There are many many reasons for that. That’s why I don’t like analog sensors but sometimes you have to use them.

First of all I would start by connecting it to oscilloscope and looking at the readings if you get crazy fluctuations most likely you have crap sensor or your wiring is terrible. If readings are fine then you need to look at uC itself. Maybe it’s the power supply to ADC maybe it’s bad ADC converter to test it you can use some bench power supply make sure it’s very accurate and outputs what you want and then take measurements with ADC this way you can narrow down your issues. But most likely it’s combination of wiring and sensor. I don’t know maybe using decoupling capacitor could help but I’m not sure if you use them on ADC inputs

Hmm, that is not a bad idea. I will give the sensors a look over with an o-scope tomorrow as well as look into if a decoupling cap can help as well.

So I began some testing of the motor with the code that I have written and have run into another bind. The code will work on an arduino uno but not the mega. Any idea why that would be the case? I am driving a bipolar stepper through the adafruit motor shield v2.