Hey Guys
Im trying to serial print data collected from the QTR-8RC with a timestamp. I have gotten it to work and I can serial print every 25ms. Once I got that working I tried to implement my code for the motors so they simply pulse a set PWM signal for a set time and then reverse it so the result is the robot will just keep moving back and fourth over the line. Its a line follower by the way. When I put both pieces of code together it does as expected and runs the loop but then serial prints the line position and time stamp after its finished pulsing the motor one way and then back the other way, so every 2 seconds. My problem is I want to keep recording data every 25ms whilst simultaneously pulsing the motors back and fourth. Thanks for your help in advanced and hope I have explained my problem well. I know the example code Blink Without Delay touches on what I want to do but I cant seem to wrap my head around it.
// MOTOR MOTOR MOTOR MOTOR
int E1 = 10; // RIGHT MOTOR PWM
int M1 = 12; // RIGHT MOTOR DIRECTION
int E2 = 11; // LEFT MOTOR PWM
int M2 = 13; // LEFT MOTOR DIRECTION
//TIMER TIMER TIMER TIMER
unsigned long time;
//SENSOR SENSOR SENSOR SENSOR
#include <QTRSensors.h>
#define NUM_SENSORS 8 // Number of Sensors Used
#define TIMEOUT 2500 // Waits for 2500 Microseconds for Sensor Outputs to go Low
#define EMITTER_PIN QTR_NO_EMITTER_PIN // Eemitter is Controlled by Digital Pin 2, No Emitter Pin
QTRSensorsRC qtrrc((unsigned char[]) {2, 3, 4, 5, 6, 7, 8, 9}, NUM_SENSORS, TIMEOUT, EMITTER_PIN);
unsigned int sensorValues[NUM_SENSORS];
void setup()
{
//MOTOR MOTOR MOTOR MOTOR
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(E1, OUTPUT);
pinMode(E2, OUTPUT);
// TIMER TIMER TIMER TIMER
Serial.begin(9600);
// SENSOR SENSOR SENSOR SENOR
for (int i = 0; i < 200; i++) // Calibration Time
{
qtrrc.calibrate(); // Reads All Sensors 10 Times at 2500 us Per Read (i.e. ~25 ms per call)
}
delay(1000);
}
void loop()
{
//MOTOR MOTOR MOTOR MOTOR
// TURN RIGHT
digitalWrite(M1, LOW); //RIGHT MOTOR REVERSE
digitalWrite(M2, HIGH); //LEFT MOTOR FORWARD
analogWrite(E1, 150); //RIGHT MOTOR PWM
analogWrite(E2, 150); //LEFT MOTOR PWM
delay(50); //TIME
// STOP
digitalWrite(M1, LOW); //STOP
digitalWrite(M2, LOW); //STOP
analogWrite(E1, 0); //STOP
analogWrite(E2, 0); //STOP
delay(1000);
// TURN LEFT
digitalWrite(M1, HIGH); //RIGHT MOTOR FORWARD
digitalWrite(M2, LOW); //LEFT MOTOR REVERSE
analogWrite(E1, 150); //RIGHT MOTOR PWM
analogWrite(E2, 150); //LEFT MOTOR PWM
delay(50); //TIME
// STOP
digitalWrite(M1, LOW); //STOP
digitalWrite(M2, LOW); //STOP
analogWrite(E1, 0); //STOP
analogWrite(E2, 0); //STOP
delay(1000);
// TIMER TIMER TIMER TIMER
Serial.print("Time: ");
time = millis();
Serial.println(time); //Prints Time Since Program Started
delay(25); // Time Stamp Sample Rate
// SENSOR SENSOR SENSOR SENSOR
unsigned int position = qtrrc.readLine(sensorValues); // Read Calibrated Sensor Values and Obtain a Measure of the Line Position from 0 to 7000
Serial.println(position); // Prints Line Positions Values from 0-7000
}
Hi.
To do something like that, you could use non-blocking delays like you mentioned. An alternative option that might be easier (since your delays are all multiples of 25ms) could be to make a function that loops some number of times, printing every 25ms. Then you could pass the function the number of times you want it to loop as an argument (or how long you want the delay to be) and use that instead of delay()
. For example:
void printDelay(int loopCycles)
{
for(loopCycles>0; loopCycles--)
{
Serial.print("Time: ");
Serial.println(millis());
delay(25);
}
return;
}
Note the timing probably won’t be exact since each line takes some time to execute. With this function, your code would look something like this:
// TURN RIGHT
digitalWrite(M1, LOW); //RIGHT MOTOR REVERSE
digitalWrite(M2, HIGH); //LEFT MOTOR FORWARD
analogWrite(E1, 150); //RIGHT MOTOR PWM
analogWrite(E2, 150); //LEFT MOTOR PWM
printDelay(2); // 50/25=2
// STOP
digitalWrite(M1, LOW); //STOP
digitalWrite(M2, LOW); //STOP
analogWrite(E1, 0); //STOP
analogWrite(E2, 0); //STOP
printDelay(40); // 1000/25 = 40
// and so on
Is there a reason you moved away from using the for loop method from your previous thread? Adding a serial print inside of that for loop and changing the delay to 25ms should also work.
Claire
Hi Claire, thanks for your response, this method I’m using now is for conducting a step test so I can create a transfer function based on yaw angle to motor supply voltage, Im hoping with this transfer function I can theoretically calculate PID values for the line follower. Will be more than happy to share results, so it can hopefully help out other people.
I am struggling to implement the advice you have given, mostly because I don’t have enough experience to understand what you mean, I cant completely wrap my head around it, but also the 25ms is just arbitrary, will definitely need to change in the future. Is it possible you could guide me on how to setup a system like the “Blink Without Delay”, my understanding and idea is it will run through the loop every 25ms or less and it will only alter the the motor direction and power if they are outside a range specified. Im hoping this way I can change the sample time with just one variable and also change the power and the amount of time that that power is delivered to the motors with ease.
Thanks Claire
Claire I got it working, instead of defining my motor direction based on time i defined it based on sensor reading so it simply bounces back and fourth between sensor 1 and 7. What i need to do know is increase the pwm value by 1 through each pass of the loop or increase by one every second.
// MOTOR MOTOR MOTOR MOTOR
int E1 = 10; // RIGHT MOTOR PWM
int M1 = 12; // RIGHT MOTOR DIRECTION
int E2 = 11; // LEFT MOTOR PWM
int M2 = 13; // LEFT MOTOR DIRECTION
//SENSOR SENSOR SENSOR SENSOR
#include <QTRSensors.h>
#define NUM_SENSORS 8 // Number of Sensors Used
#define TIMEOUT 2500 // Waits for 2500 Microseconds for Sensor Outputs to go Low
#define EMITTER_PIN QTR_NO_EMITTER_PIN // Eemitter is Controlled by Digital Pin 2, No Emitter Pin
QTRSensorsRC qtrrc((unsigned char[]) {2, 3, 4, 5, 6, 7, 8, 9}, NUM_SENSORS, TIMEOUT, EMITTER_PIN);
unsigned int sensorValues[NUM_SENSORS];
void setup() {
Serial.begin(9600);
//MOTOR MOTOR MOTOR MOTOR
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(E1, OUTPUT);
pinMode(E2, OUTPUT);
// SENSOR SENSOR SENSOR SENOR
for (int i = 0; i < 200; i++) // Calibration Time
{
qtrrc.calibrate(); // Reads All Sensors 10 Times at 2500 us Per Read (i.e. ~25 ms per call)
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
unsigned int position = qtrrc.readLine(sensorValues);
if(position==0)
{
// TURN LEFT
digitalWrite(M1, HIGH); //RIGHT MOTOR REVERSE
digitalWrite(M2, LOW); //LEFT MOTOR FORWARD
analogWrite(E1, 80); //RIGHT MOTOR PWM
analogWrite(E2, 80); //LEFT MOTOR PWM
}
if(position==7000)
{
// TURN RIGHT
digitalWrite(M1, LOW); //RIGHT MOTOR REVERSE
digitalWrite(M2, HIGH); //LEFT MOTOR FORWARD
analogWrite(E1, 80); //RIGHT MOTOR PWM
analogWrite(E2, 80); //LEFT MOTOR PWM
}
Serial.println(position); // Prints Line Positions Values from 0-7000
Serial.println(millis()); // Prints the Time Since Program Started Running
delay(25); // Sample Rate
}
I am not sure if your last post was asking for suggestions on how to ramp up and down the speed of your motors or just letting us know what your next step on your project is. If you need some help, could you state your question or what you are having trouble with more clearly?
-Claire