Why can't X be used as a function? - arduino

Sorry for the messy codebase. I am new to C++.
I'm trying to tie a loop and function together. (1) A moisture sensor and (2) a servo to turn a lever on and off based on moisture.
I'm receiving an error that 'servo' cannot be used as a function. I've tried changing servo to some other name. I'm not using servo anywhere else, such as a variable, so that doesn't seem like the issue.
Does anyone have any other advice?
#include "Servo.h"
Servo myservo; // create servo object to control a servo
int pos = 0; // servo position variable
#define SensorPin A0
float sensorValue = 0;
bool lever = 0; // soil moisture sensor variable; 0 = dry; 1 = wet;
bool pump = 0; // pump is set to 0, which = off
// servo function
void servo(bool);
void setup() {
Serial.begin(9600); // soil moisture sensor setup
myservo.attach(9); // servo setup
}
// soil moisture sensor loop
void loop() {
for (int i = 0; i <= 100; i++) {
sensorValue = sensorValue + analogRead(SensorPin);
delay(20);
}
sensorValue = sensorValue/100.0;
Serial.print("Moisture level: ");
Serial.print(sensorValue);
Serial.print(";");
if(sensorValue > 1000) {
lever = 0; // dry
}
if(sensorValue < 1000) {
lever = 1; // wet
}
switchOnOff(lever);
delay(1000);
}
// define the servo function
void switchOnOff(bool lever) {
Serial.print(" Lever: ");
Serial.print(lever);
Serial.print(";");
Serial.print(" Pump: ");
Serial.print(pump);
Serial.println(";");
if(lever == 0 && pump == 0) { // it is dry and pump is off, pump needs to be turned on
for (pos = 90; pos <= 180; pos++) { // goes from 0 degrees to 90 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
delay(4000);
for (pos = 180; pos >= 90; pos--) { // goes from 90 degrees to 0 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
pump = 1; // noting that pump is on
}
if(lever == 0 && pump == 1) { // it is dry and pump is on
return; // do nothing, return
}
if(lever == 1 && pump == 1) { // it is wet and pump is on, pump needs to be turned off
for (pos = 90; pos <= 180; pos++) { // goes from 90 degrees to 0 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
delay(4000);
for (pos = 180; pos >= 90; pos--) { // goes from 0 degrees to 90 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
pump = 0; // noting that pump is off
}
if(lever == 1 && pump == 0) { // it is wet and pump is off
return; // do nothing, return
}
}
Thank you.

The problem is in that you try to use the servo() function before properly declaring it. First, you need to declare a function before it can be mentioned in your code. Second, your definition for the servo() is incorrect. The int servo(lever), where lever is not a type. You should look toward the following: int servo(bool lever);, where lever is a parameter of type bool which the servo() function takes.
Then, your function does not return anything, it only has some "side-effects" such as myservo.write(pos);. So, it should be void.
Try the following arrangement:
#include "Servo.h"
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
// Declare the function
void servo(bool);
int pos = 0; // variable to store the servo position
#define SensorPin A0
float sensorValue = 0;
bool lever = 0; // lever is global variable of type bool
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.begin(9600);
}
void loop() {
for (int i = 0; i <= 100; i++) {
sensorValue = sensorValue + analogRead(SensorPin);
delay(1);
}
sensorValue = sensorValue/100.0;
Serial.println(sensorValue);
delay(30);
if(analogRead(0 > 100)) {
lever = 1;
}
if(analogRead(0 < 100)) {
lever = 0;
}
servo(lever);
}
// Define the function
void servo(bool lever) {
if(lever == 1) { // On
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
}
}
if(lever == 0) { // Off
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
}
}
}
P.S. There was also a mess with setup() being redefined here and there.

Related

Question on Two servo project activated by timer and water level sensor

I am using a arduino uno in an attempt to power two servos. Servo A should open for a couple seconds every 24 hours OR if button A is pressed. Servo B should open for a couple seconds if the water level sensor reads below 300 OR if button B is pressed. The code below works fine when I only include one servo, but adding the code for servo B ruins everything.
#include <Servo.h>
Servo myservoA;
Servo myservoB;
const int BUTTONA_PIN = 8;
const int BUTTONB_PIN = 6;
const int SERVOA_PIN = 9;
const int SERVOB_PIN = 7;
unsigned long dayTimer_ms = 0;
unsigned long autoOpenDelay_ms = 86400000;
int angle = 0;
int waterSensor = A0;
int waterLevel = 0;
void setup(){
myservoA.attach(SERVOA_PIN);
myservoB.attach(SERVOB_PIN);
pinMode(BUTTONA_PIN, INPUT_PULLUP);
pinMode(BUTTONB_PIN, INPUT_PULLUP);
myservoA.write(0);
myservoB.write(0);
}
void loop() {
if(millis() - dayTimer_ms > autoOpenDelay_ms)
{
dayTimer_ms = millis();
myservoA.write(180); //(open?)
delay(8000);
myservoA.write(0);
}
if(millis()<dayTimer_ms)//overflow handling (in case this runs for more than 50 days straight)
{
dayTimer_ms = millis();
}
if (!digitalRead(BUTTONA_PIN) && angle != 180)
{
angle = 180;
myservoA.write(angle);
}
if (digitalRead(BUTTONA_PIN) && angle != 0)
{
angle = 0;
myservoA.write(angle);
}
if (!digitalRead(BUTTONB_PIN) && angle != 180)
{
angle = 180;
myservoB.write(angle);
}
if (digitalRead(BUTTONB_PIN) && angle != 0)
{
angle = 0;
myservoB.write(angle);
}
int waterLevel = analogRead(waterSensor);
if (waterLevel <= 300){
myservoB.write(180);
delay(8000);
myservoB.write(0);
}
}
You are actually super close!
You just need to make a second variable to track angleA separately from angleB. So you should initialize another variable at the top "angleB" to zero and then replace "angle" with this new variable everywhere below line 52
#include <Servo.h>
Servo myservoA;
Servo myservoB;
const int BUTTONA_PIN = 8;
const int BUTTONB_PIN = 6;
const int SERVOA_PIN = 9;
const int SERVOB_PIN = 7;
unsigned long dayTimer_ms = 0;
unsigned long autoOpenDelay_ms = 86400000;
int angleA = 0;
int angleB = 0;
int waterSensor = A0;
int waterLevel = 0;
void setup(){
myservoA.attach(SERVOA_PIN);
myservoB.attach(SERVOB_PIN);
pinMode(BUTTONA_PIN, INPUT_PULLUP);
pinMode(BUTTONB_PIN, INPUT_PULLUP);
myservoA.write(0);
myservoB.write(0);
}
void loop() {
if(millis() - dayTimer_ms > autoOpenDelay_ms)
{
dayTimer_ms = millis();
myservoA.write(180); //(open?)
delay(8000);
myservoA.write(0);
angleA = 0;
}
if(millis()<dayTimer_ms)//overflow handling (in case this runs for more than 50 days straight)
{
dayTimer_ms = millis();
}
if (!digitalRead(BUTTONA_PIN) && angleA != 180)
{
angleA = 180;
myservoA.write(angleA);
}
if (digitalRead(BUTTONA_PIN) && angleA != 0)
{
angleA = 0;
myservoA.write(angleA);
}
if (!digitalRead(BUTTONB_PIN) && angleB != 180)
{
angleB = 180;
myservoB.write(angleB);
}
if (digitalRead(BUTTONB_PIN) && angleB != 0)
{
angleB = 0;
myservoB.write(angleB);
}
int waterLevel = analogRead(waterSensor);
if (waterLevel > 300 && angleB != 0)
{
myservoB.write(0);
angleB = 0;
}
else if (waterLevel < 200 && angleB != 180){
myservoB.write(180);
angleB = 180;
}
}
the bottom two levels may need to be adjusted (200 and 300). Basically this creates a slight de-bounce. By separating the levels at which the water turns on and turns off, it keeps the system from jittering right at the limit (constantly turning on and off). That being said, depending on the accuracy of your sensor and how important precise level control is in your application, you may want to tighten or move these values around a bit.

MPU6050 FIFO overflow and freezing problems

Im using the sensor MPU6050 to control movements of my robotic arm. The codes work fine when it is a standalone program but i keep encountering 'FIFO overflow' when the codes are complied into the main program. This is the code that i am using.
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
RF24 radio(9, 8); // CE, CSN
const byte address[6] = "00001";
const int AccReadings = 10;
//Wrist Roll
int DataX[AccReadings];
int WRIndex = 0;
int WRtotal = 0;
int WRaverage = 0;
//Wrist Pitch
int DataY[AccReadings];
int WPIndex = 0;
int WPtotal = 0;
int WPaverage = 0;
//Shoulder Lift
int DataY2[AccReadings];
int SLIndex = 0;
int SLtotal = 0;
int SLaverage = 0;
//Elbow Lift
int ELaverage = 0;
//Arm Rotation
int ARaverage = 0;
float correct;
#define OUTPUT_READABLE_YAWPITCHROLL
#define INTERRUPT_PIN 2
bool blinkState = false;
// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
struct Sensor_Data
{
int WristRoll;
int WristPitch;
int ShoulderLift;
int ElbowLift;
int ArmRotation;
};
Sensor_Data data;
//Interrupt Detection
volatile bool mpuInterrupt = false;
void dmpDataReady()
{
mpuInterrupt = true;
}
void setup()
{
radio.begin();
radio.openWritingPipe(address);
radio.setPALevel(RF24_PA_MIN);
radio.stopListening();
//Zero-fill Arrays
for (int i = 0; i < AccReadings; i++)
{
DataX[i] = 0;
}
for (int j = 0; j < AccReadings; j++)
{
DataY[j] = 0;
}
for (int k = 0; k < AccReadings; k++)
{
DataY2[k] = 0;
}
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
Wire.setClock(400000);
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200);
while (!Serial);
mpu.initialize();
pinMode(INTERRUPT_PIN, INPUT);
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(49);
mpu.setYGyroOffset(-18);
mpu.setZGyroOffset(9);
mpu.setZAccelOffset(4427);
if (devStatus == 0)
{
mpu.setDMPEnabled(true);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
}
else
{
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
// Serial.print(F("DMP Initialization failed (code "));
//Serial.print(devStatus);
//Serial.println(F(")"));
}
}
void loop()
{
/*smoothWR();
movementWR();
smoothWP();
movementWP();
smoothSL();
movementSL();*/
ElbowMovement();
radio.write(&data, sizeof(Sensor_Data));
}
void smoothWR()
{
WRtotal = WRtotal - DataX[WRIndex];
DataX[WRIndex] = analogRead(A0);
WRtotal = WRtotal + DataX[WRIndex];
WRIndex = WRIndex + 1;
if (WRIndex >= AccReadings)
{
WRIndex = 0;
}
WRaverage = WRtotal / AccReadings;
//Serial.println(WRaverage);
}
void movementWR()
{
WRaverage = map(WRaverage, 278, 419, 0, 180);
data.WristRoll = constrain(WRaverage, 0, 180);
//Serial.println(data.WristRoll);
}
void smoothWP()
{
WPtotal = WPtotal - DataY[WPIndex];
DataY[WPIndex] = analogRead(A1);
WPtotal = WPtotal + DataY[WPIndex];
WPIndex = WPIndex + 1;
if (WPIndex >= AccReadings)
{
WPIndex = 0;
}
WPaverage = WPtotal / AccReadings;
//Serial.println(WPaverage);
}
void movementWP()
{
WPaverage = map(WPaverage, 280, 421, 0 , 135);
data.WristPitch = constrain(WPaverage, 0, 135);
//Serial.println(data.WristPitch);
}
void smoothSL()
{
SLtotal = SLtotal - DataY2[SLIndex];
DataY2[SLIndex] = analogRead(A2);
SLtotal = SLtotal + DataY2[SLIndex];
SLIndex = SLIndex + 1;
if (SLIndex >= AccReadings)
{
SLIndex = 0;
}
SLaverage = SLtotal / AccReadings;
//Serial.println(SLaverage);
}
void movementSL()
{
SLaverage = map(SLaverage, 410, 270, 0 , 180);
data.ShoulderLift = constrain(SLaverage, 35, 180);
//Serial.println(data.ShoulderLift);
}
void ElbowMovement()
{
// if programming failed, don't try to do anything
if (!dmpReady) return;
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize)
{
if (mpuInterrupt && fifoCount < packetSize)
{
// try to get out of the infinite loop
fifoCount = mpu.getFIFOCount();
}
}
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024)
{
// reset so we can continue cleanly
mpu.resetFIFO();
fifoCount = mpu.getFIFOCount();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
}
else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT))
{
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
// Get Yaw, Pitch and Roll values
#ifdef OUTPUT_READABLE_YAWPITCHROLL
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
// Yaw, Pitch, Roll values - Radians to degrees
ypr[0] = ypr[0] * 180 / M_PI;
ypr[1] = ypr[1] * 180 / M_PI;
ypr[2] = ypr[2] * 180 / M_PI;
// Skip 300 readings (self-calibration process)
if (int l = 0; l <= 300) {
correct = ypr[0]; // Yaw starts at random value, so we capture last value after 300 readings
l++;
}
// After 300 readings
else {
ypr[0] = ypr[0] - correct; // Set the Yaw to 0 deg - subtract the last random Yaw value from the currrent value to make the Yaw 0 degrees
// Map the values of the MPU6050 sensor from -90 to 90 to values suatable for the servo control from 0 to 180
ELaverage = map(ypr[0], -90, 90, 0, 180);
data.ElbowLift = constrain(ELaverage, 30, 110);
ARaverage = map(ypr[1], -90, 90, 0, 180);
data.ArmRotation = constrain(ARaverage, 0, 180);
//Serial.println(data.ElbowLift);
Serial.println(ypr[1]);
}
#endif
}
}
Is there any ways to get rid of the FIFO overflow? Also When i tried to used Jeff Rowberg's example codes MPU6050_DMP6 the program will freeze after a few seconds. Is there any solution to that? These are the example codes that i am using.
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
float correct;
int j = 0;
#define OUTPUT_READABLE_YAWPITCHROLL
#define INTERRUPT_PIN 2
bool blinkState = false;
// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
//Interrupt Detection
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
Wire.setClock(400000);
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(38400);
while (!Serial);
mpu.initialize();
pinMode(INTERRUPT_PIN, INPUT);
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(17);
mpu.setYGyroOffset(-69);
mpu.setZGyroOffset(27);
mpu.setZAccelOffset(1551);
if (devStatus == 0)
{
mpu.setDMPEnabled(true);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
}
else
{
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
// Serial.print(F("DMP Initialization failed (code "));
//Serial.print(devStatus);
//Serial.println(F(")"));
}
}
void loop()
{
if (!dmpReady) return;
if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer))
{
#ifdef OUTPUT_READABLE_YAWPITCHROLL
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
if (j <= 300)
{
correct = ypr[0]; // Yaw starts at random value, so we capture last value after 300 readings
j++;
}
else
{
ypr[0] = ypr[0] - correct;
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI);
Serial.print("\t");
Serial.println(ypr[2] * 180/M_PI);
}
#endif
}
}
You're using DMP (Digital Motion Processor) with mean calculation running on the MPU itself, this gives more precise and less CPU consumption but you need to update the FIFO frequently or the track goes wrong.
Encountering 'FIFO overflow' means your loop code was too slow, you should increase the speed of another task in your loop code. Or just use other code that not use the DMP.

I'm missing "stuff" in my code and I don't get it

I'm newbie to coding and for the last few days, I've been trying to make a servo rotate 180 degrees by typing 1 on an app on my phone connected to an HC 05 Bluetooth module. When I type one the servo rotates 180 degrees when I type 0 the servo rotates 180 degrees the other way. This is what I've done so far by combining bits of different codes. Can you please help resolve what's wrong? (I really don't get it) Here's the code :
#include <Servo.h>
char data = 0;
int pos = 0;
Servo servo;
void setup()
{
servo.attach(9);
}
void loop(){
data = Serial.read();
Serial.print(data);
Serial.print("\n");
if(data == '1')
digitalWrite(pos = 0; pos <= 180; pos += 1) {
servo.write(pos);
delay(15);
else if(data == '0')
digitalWrite(pos = 180; pos >= 0; pos -= 1) {
servo.write(pos);
delay(15);
}
}
Thank you for your time!
PS: please forgive the spelling mistakes
You probably want something like this:
#include <Servo.h>
int data = 0;
int pos = 0;
int degrees = 30;
//int degrees = 180;
Servo servo;
void setup()
{
Serial.begin(9600);
servo.attach(9);
}
void loop(){
if (Serial.available() > 0) {
data = Serial.read();
Serial.println(data);
if(data == '1') {
for (pos = 0; pos <= degrees; pos++) {
servo.write(pos);
delay(15);
}
}
else if(data == '0') {
for (pos = degrees; pos >= 0; pos--) {
servo.write(pos);
delay(15);
}
}
}
}
Try with 30 degrees first, since not all servos support 180 degrees.

Transition between two Steppers with independently assigned cues

I am going to use two step motors, two easy-drivers, one arduino uno.
Each step motors have gear to rotate, front and back.
First, I'd like to assign multiple rotation cues for each steppers. such as,
int step1cue1 = 329
int step1cue2 = 582
int step1cue3 = 1038
int step1 cue4 = 1790
...
int step2cue1 = 568
int step2cue2 = 1004
int step2cue3 = 1928
int step2cue4 = 3592
...
and each stepper needs minimum 0 and maximum value, such as,
int step1maxcue = 8372
int step2maxcue = 8421
each rotation speed and acceleration need to be set and controllable as well.
I would like to use rotation speed = 0 to make the stepper stopped at the cue.
** Operation
Both steppers start from 0,
First, stepper1 rotates to randomly chosen cue from its step1cues, when it almost reaches to the chosen cue, stepper2 starts to rotate to randomly chosen cue from step2cues.(stepper1 stopped at the cue with speed=0), when step2 almost reaches to its cue, stepper1 starts to rotate to another randomly chosen step1cue (not the current cue).. (stepper2 stops with speed=0).. and repeat this transition between two steppers.
Could you please help me with this code?
I would like to use the code from this,
#include <AccelStepper.h>
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
int pos1 = 3600;
int pos2 = 5678;
void setup()
{
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(2000);
stepper2.setAcceleration(800);
}
void loop()
{
if (stepper1.distanceToGo() == 0)
{
pos1 = -pos1;
stepper1.moveTo(pos1);
}
if (stepper2.distanceToGo() == 0)
{
pos2 = -pos2;
stepper2.moveTo(pos2);
}
stepper1.run();
stepper2.run();
}
I don't know the AccelStepper library, so I can be wrong, but this should do what you requested:
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = { 329, 582, 1038, 1790 ...};
const int step2cues[] = { 568, 1004, 1928, 3592 ...};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
movingStepper = 1;
}
}
stepper1.run();
stepper2.run();
}
THRESHOLD is the "almost" in your sentence: when it is nearer than this value it will start moving the other motor. Note: the cues should be mode distant one from the other than twice the threshold value, so you won't have mixed conditions (I mean with that threshold the minimum distance from one cue and ANY other should be 40).
And by the way, you don't need to set speed to 0: when the stepper reaches the position it will halt by itself.
EDIT:
The OP asked three more features (print the next cue when chosen, print on serial the current position, set a switch when the motor reaches the cue), so here they are.
First of all I'd separate the second and third feature from the previous code, for clarity reasons. I chose to run that code only when the position changes, but this can easily be changed to
print that code only after a fixed amount of change (e.g. only after a change of 50 or more)
print that code at fixed amount of time (e.g. 0.5 s)
Anyway, here is the code:
int currentPos1 = -1;
int currentPos2 = -1;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if (currentPos1 != stepper1.currentPosition())
{ // Stepper 1 has moved
currentPos1 = stepper1.currentPosition()
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
Serial.print("Motor 1 pos: ");
Serial.println(currentPos1);
}
if (currentPos2 != stepper2.currentPosition())
{ // Stepper 2 has moved
currentPos2 = stepper2.currentPosition()
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
Serial.print("Motor 2 pos: ");
Serial.println(currentPos2);
}
stepper1.run();
stepper2.run();
}
If you choose to modify it in order not to receive frequent motor updates (e.g. by showing the message every half a second) you should move the Stepper X has reached the final position block outside the control, so that it can be executed every iteration:
unsigned long lastShownMessages = 0;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if ((millis() - lastShownMessages) > 500)
{ // More than 500 ms passed since last update:
Serial.print("Motor 1 pos: ");
Serial.println(stepper1.currentPosition());
Serial.print("Motor 2 pos: ");
Serial.println(stepper2.currentPosition());
lastShownMessages += 500;
}
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
stepper1.run();
stepper2.run();
}
PLUS, for a calibration purpose, can I see the rotation value (increment) of the stepper on the Server Monitor ? I can set the speed really low and let it roll, then I could know cue values for the stepcues that I need to set.
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
const int step2cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 4, 3);
AccelStepper stepper2(1, 7, 6);
int switch1 = 12;
int switch2 = 13;
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
Serial.begin(9600);
pinMode(switch1, OUTPUT);
pinMode(switch2, OUTPUT);
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.println("2");
Serial.println(nextpos);
movingStepper = 2;
if ( nextpos = stepper2.targetPosition() ){
digitalWrite(switch1, HIGH);
}
else {
digitalWrite(switch1, LOW);
}
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.println("1");
Serial.println(nextpos);
movingStepper = 1;
if ( nextpos = stepper1.targetPosition() ){
digitalWrite(switch2, HIGH);
}
else {
digitalWrite(switch2, LOW);
}
}
}
stepper1.run();
stepper2.run();
}

1820 Dallas Temperture sensor, incorrect value returned

When I run a piece of code that only gathers values from the temp sensor it returns the correct values.
when I integrate this functionality into a larger piece of code it constantly returns -127 degrees.
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPP.h>
#include <LiquidCrystal.h>
#define ONE_WIRE_BUS 9
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature TempSensor(&oneWire);
USB Usb; // create usb
BTD Btd(&Usb); // create bluetooth dongle instance
SPP SerialBT(&Btd, "Arduino", "0000"); // set device name and pin
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // create lcd instance using declared pins
int LightPin = A0; // pin connected to light sensor
int LcdType = 0; // variable for lcd display
int state; // variable for storing incoming data
int LDRvalue = 0; // value from light sensor
int totalLdr = 0;
int totalLdrNums = 0;
String output = ""; // output string for light sensor
String output2 = ""; // output string for temp sensor
int tempvalue = 0; // value from temp sensor
int totalTemp = 0;
int totalTempNums = 0;
float celsius = 0; // temp in celsius
void setup() {
Serial.begin(9600); // Begin serial comms at speed 9600
if (Usb.Init() == -1) { // if usb hasn't been initilsed
while(1); //wait
}
lcd.begin(16, 2); // set up lcd with 16 coloums and 2 rows
pinMode(LightPin, INPUT); // declare light pin as input
printStart(); // run printStart method
LcdType = 1; // set lcd display type to 1
TempSensor.begin();
}
void loop() {
Usb.Task(); // polls connected devices for status
if(SerialBT.connected) { // if BT connected
if(SerialBT.available() > 0){ // and BT is available
state = SerialBT.read() - '0'; // read incoming value and turn into regular int (0 - 9 in ascii is 48 - 57)
if(state == 0){ // if value read is zero
checkLightValue(); // run checkLightValue method
SerialBT.write(output[0]); // send first value in string
delay(50); // delay before sending next value
SerialBT.write(output[1]); // send second value
delay(50); // delay before sending next value
SerialBT.write(output[2]); // send third value
}
if(state == 1){ // if value read is 1
checkTempValue();
SerialBT.write(output2[0]); // send first value
delay(50); // delay before sending next value
SerialBT.write(output2[1]); // send second value
delay(50); // delay before sending next value
SerialBT.write(output2[3]); // send third value
delay(50); // delay before sending next value
SerialBT.write(output2[5]); // send fourth value
delay(50); // delay before sending next value
}
if(state == 2){
//Restart();
SerialBT.disconnect();
}
if(state == 3){
LcdType = 1;
}
if(state == 4){
LcdType = 2;
}
if(state == 5){
LcdType = 3;
}
if(LcdType == 1){ // if lcd type variable = 1
printLcd();} // run printLcd method
if (LcdType == 2){
printLcd2();
}
if(LcdType == 3){
printLcd3();
}
}
}
}
//void (*resetFunc)(void) = 0;
void checkLightValue(){
output = ""; // reset output string to nothing
LDRvalue = analogRead(LightPin); // read in light value
totalLdr = totalLdr + LDRvalue;
totalLdrNums = totalLdrNums + 1;
int LDR1 = LDRvalue / 100; // get int 1 from value
int twod = LDRvalue - (LDR1 * 100); // get int 2 and 3 from value
int LDR2 = twod / 10; // get int 2 from value
int LDR3 = twod - (LDR2 * 10); // get int 3 from value
output += LDR1; //
output += LDR2; //
output += LDR3; // appends values to string
}
void checkTempValue(){
output2 = ""; // reset output string to nothing
TempSensor.requestTemperatures();
Serial.println(TempSensor.getTempCByIndex(0));
celsius = TempSensor.getTempCByIndex(0);
totalTemp = totalTemp + celsius;
totalTempNums = totalTempNums + 1;
int c1 = celsius / 100; // get first int from value
int twod = celsius - (c1 * 100); //
int c2 = twod / 10;
int c3 = twod - (c2 *10);
output2 += c1; //
output2 += c2; //
output2 += c3; // add values to string to send
}
void printLcd(){
lcd.clear(); // clear lcd
lcd.print("LDR : "); lcd.print(LDRvalue); // display current ldr value
lcd.setCursor(0,1); // set cursor to second row
lcd.print("Temp : "); lcd.print(celsius); // display current temp value on row 2
}
void printLcd2(){
int Averagevalue = totalLdr / totalLdrNums;
lcd.clear();
lcd.print("Average light :");
lcd.setCursor(0,1);
lcd.print(Averagevalue);
}
void printLcd3(){
int Averagevalue = totalTemp / totalTempNums;
lcd.clear();
lcd.print("Average temp :");
lcd.setCursor(0,1);
lcd.print(Averagevalue);
}
void printStart(){
lcd.clear(); // clear lcd
lcd.setCursor(1,1); // set cursor on second row
lcd.print("Waiting for a Connection ?"); // print message
for(int x=1; x<16; x++) { // do following 15 times
lcd.setCursor(x,0); // set cursor to first row
lcd.print("Arduino Started"); // print message // doing this as lcd scrolls means the top line (message) appears static while the bottom line (message) scrolls
lcd.scrollDisplayLeft(); // scroll display left
delay(250); // delay before moving again
}
}

Resources