I'm trying to control a motor through IoT, and was able to get the motor to work on its own, and the IoT from the IoT Remote app to work on its own, but not both of them together and I'm stumped.
The dashboard looks like this:
The scheduler isn't being used yet.
Here is my code:
/*
Sketch generated by the Arduino IoT Cloud Thing "Coop Control"
https://create.arduino.cc/cloud/things/4217e43c-751f-4f0f-9f0c-3b0e77887e97
Arduino IoT Cloud Variables description
The following variables are automatically generated and updated when changes are made to the Thing
CloudSchedule schedule_variable;
bool door_Motor;
Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
which are called when their values are changed from the Dashboard.
These functions are generated with the Thing and added at the end of this sketch.
*/
#include "thingProperties.h"
#define ENCA 2 // YELLOW
#define ENCB 3 // WHITE
#define PWM 5
#define IN2 6
#define IN1 7
volatile int posi = 0; // specify posi as volatile: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/
long prevT = 0;
float eprev = 0;
float eintegral = 0;
int dir;
int pos;
int target;
float pwr;
void setup() {
Serial.begin(9600);
delay(500);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(ENCA,INPUT);
pinMode(ENCB,INPUT);
attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
pinMode(PWM,OUTPUT);
pinMode(IN1,OUTPUT);
pinMode(IN2,OUTPUT);
Serial.println("target pos");
// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
/*
The following function allows you to obtain more information
related to the state of network and IoT Cloud connection and errors
the higher number the more granular information you’ll get.
The default is 0 (only errors).
Maximum is 4
*/
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
}
void loop() {
ArduinoCloud.update();
//This uses the scheduler to turn the LED on at a set time and duration every day. Use to toggle the door open
//and close every day at a specific time.
// if(schedule_variable.isActive()){
// digitalWrite(LED_BUILTIN, HIGH);
// }
// // whenever the job is "not active", turn off the LED
// else{
// digitalWrite(LED_BUILTIN, LOW);
// }
// set target position
//target = 7000;
// PID constants
float kp = 1;
float kd = 0.025;
float ki = 0.0;
// time difference
long currT = micros();
float deltaT = ((float) (currT - prevT))/( 1.0e6 );
prevT = currT;
// Read the position
pos = 0;
noInterrupts(); // disable interrupts temporarily while reading
pos = posi;
interrupts(); // turn interrupts back on
// error
int e = target - pos;
// derivative
float dedt = (e-eprev)/(deltaT);
// integral
eintegral = eintegral + e*deltaT;
// control signal
float u = (kp*e + kd*dedt + ki*eintegral);
// motor power
pwr = fabs(u);
if(pwr > 255){
pwr = 255;
}
// motor direction
//int dir = 1; //Clockwise
//if(u<0){
// dir = -1;
//}
checkTarget(target);
// signal the motor
if (door_Motor == 1) {
target = 7000;
dir = 1;
setMotor(dir,pwr,PWM,IN1,IN2);
} else if (door_Motor == 0) {
target = 0;
dir = -1;
setMotor(dir,pwr,PWM,IN1,IN2);
}
//On door open or close
onDoorMotorChange();
Serial.println(door_Motor);
// store previous error
eprev = e;
if (e < 15) {
//Serial.print("Motor off");
dir = 0;
//pwr = 0;
}
if (e > 15) {
Serial.print(target);
Serial.print(" ");
Serial.print(pos);
Serial.println();
}
}
void checkTarget(int target) {
if (target == 7000 && pos == 0) {
dir = 1; //CW
} else if (pos > 6500){
delay(1000);
target = 0;
dir = -1; //CCW
} else if (pos < 0) {
dir = 0;
}
}
void setMotor(int dir, int pwmVal, int pwm, int in1, int in2){
analogWrite(pwm,pwmVal);
if(dir == 1){
digitalWrite(in1,HIGH);
digitalWrite(in2,LOW);
}
else if(dir == -1){
digitalWrite(in1,LOW);
digitalWrite(in2,HIGH);
}
else{
digitalWrite(in1,LOW);
digitalWrite(in2,LOW);
}
}
void readEncoder(){
int b = digitalRead(ENCB);
if(b > 0){
posi++;
}
else{
posi--;
}
}
/*
Since DoorMotor is READ_WRITE variable, onDoorMotorChange() is
executed every time a new value is received from IoT Cloud.
*/
void onDoorMotorChange() {
// Add your code here to act upon DoorMotor change
if (door_Motor == 1) {
digitalWrite(LED_BUILTIN, HIGH);
} else if (door_Motor == 0) {
digitalWrite(LED_BUILTIN, LOW);
}
}
/*
Since ScheduleVariable is READ_WRITE variable, onScheduleVariableChange() is
executed every time a new value is received from IoT Cloud.
*/
void onScheduleVariableChange() {
// Add your code here to act upon ScheduleVariable change
}
I'm pretty sure how I have the motor set up currently doesn't work, but that's okay I'm just trying to iron out this IoT thing. At the very least the motor should be turning on and off when I toggle the switch on the dashboard. I'm printing the door_Motor variable to serial and it just shows a constant 0 no matter what the switch is set to.
When I was testing the IoT part on its own, the variable would update almost instantly. Maybe something with the loop and motor is preventing that speedy update? I saw one other forum post that said their variables took 7-30 minutes to update. I think I also don't quite understand how the onDoorMotorChange function is being used, but I tried a couple different things with that too and it didn't seem to change anything. Any suggestions are appreciated, thanks.