Arduino output pin outputs random activity - c

I am working on an Arduino project controlling a DIY RC truck that reads the output pins of an RC reciever and is supposed to PWMs a couple of pins accordingly. The pins are hooked onto a motor controller that takes PWM.
That is where the problem comes in. My reverse is working perfectly, but on the pin that does forward, I only get random activity. I'm using the Arduino Mega 2560.
Here is the code. The problem has been posted below it:
#include <Servo.h>
//Create variables for three channels
int RXCH[3];
volatile int RXSG[3];
int RXOK[3];
int PWMSG[3];
byte vooruit;
byte achteruit;
Servo stuur;
int mv = 13;
int ma = 10;
void setup() {
Serial.begin(115200);
stuur.attach(8);
//Assign PPM input pins. The receiver output pins are conected as below to non-PWM Digital connectors:
RXCH[0] = 6; //Throttle
RXCH[1] = 7; //Steering
//RXCH[2] = 5; //Nothing yet
//RXCH[3] = 2; //Nothing yet
//RXCH[4] = 7; //Nothing yet
//RXCH[5] = 8; //Nothing yet
for (int i = 0; i < 3; i++){
pinMode(RXCH[i], INPUT);
}
//TCCR1B = TCCR1B & 0b11111000 | 0x01;
//TCCR2B = TCCR2B & 0b11111000 | 0x01;
}
void loop() {
// Read RX values
for (int i = 0; i < 3; i++){ //For each of the 6 channels:
RXSG[i] = pulseIn(RXCH[i], HIGH, 20000); //Read the receiver signal
if (RXSG[i] == 0) { //Error catching
RXSG[i] = RXOK[i];
} else {
RXOK[i] = RXSG[i];
}
//Substitute the high values to a value between -255 and 255
PWMSG[0] = map(RXSG[0], 1000, 2000, -255, 255);
//Servo values, calibrated according to my steering servo.
PWMSG[1] = map(RXSG[1], 1000, 2000, 24, 169);
//Make sure that the value stays within the desired boundaries.
constrain (PWMSG[i], -255, 255);
//For debugginf purposes
Serial.print(" || Ch: ");
Serial.print(i);
Serial.print(" / PWMSG: ");
Serial.print(PWMSG[i]);
}
delay (5);
// Car goes forwards
if (PWMSG[0] > 40)
{
MV();
}
// Car goes backwards
if (PWMSG[0] < -40)
{
MA();
}
// Car stops
else
{
stopmotor();
}
stuur.write(PWMSG[1]);
Serial.println();
}
void MV()
{
vooruit = PWMSG[0];
analogWrite (mv, vooruit);
digitalWrite (ma, LOW);
Serial.print(" vooruit: ");
Serial.print(vooruit);
}
void MA()
{
achteruit = abs(PWMSG[0]);
analogWrite (ma, achteruit);
digitalWrite (mv, LOW);
Serial.print(" achteruit: ");
Serial.print(achteruit);
}
void stopmotor()
{
digitalWrite (ma, LOW);
digitalWrite (mv, LOW);
}
I don't really know if the code is considered pretty, or if I made some basic mistakes for that matter.
This is one of my first projects that I tried to do the right way, making comments and such, all well commented criticism is welcome.
What the code is supposed to do:
Move the stick on the transmitter forwards, the car goes forwards, and speed should be according to position of the stick.
Move the stick on the transmitter backwards, the car goes backwards, and speed should be according to position of the stick.
Move stick on the transmitter left or right, the servo in the car should react according to the value the Arduino calculated. You might wonder why I don't place the servo directly on the transmitter. Well, that's because I have many more future things in mind with this project, and now I can calibrate it way easier.
Problem:
When I move the stick on the transmitter forwards, and the Serial monitor is open, I get the right values on the Serial monitor, but the LED present on pin 13 just randomly blinks, very dim I must say.
I already tried to replace things like byte with int, but it had no effect. The rest of the code works fine.
Using some new code, I get a Serial response from every "stage", except the final stages that controls the pins.
#include <Servo.h>
//Create variables for channels
Servo wheel;
int MFORWARD_PIN = 13;
#define MBACKWARD_PIN 10
#define WHEEL_PIN 8
#define THROTTLE_PIN 6
#define STEERING_PIN 7
void setup() {
Serial.begin(115200);
wheel.attach(WHEEL_PIN);
pinMode(THROTTLE_PIN, INPUT);
pinMode(STEERING_PIN, INPUT);
pinMode(MFORWARD_PIN, OUTPUT);
pinMode(MBACKWARD_PIN, OUTPUT);
//TCCR1B = TCCR1B & 0b11111000 | 0x01;
//TCCR2B = TCCR2B & 0b11111000 | 0x01;
}
void loop() {
int throttle = read_throttle();
int steering = read_steering();
delay (5);
throttle_handle(throttle);
steering_handle(steering);
}
// Read RX values
int read_throttle(){
int throttle = pulseIn(THROTTLE_PIN, HIGH, 20000);
throttle = map(throttle, 1000, 2000, -255, 255); //Substitute the high values to a value between -255 and 255.
constrain (throttle, -255, 255); //Make sure that the value stays within the desired boundaries.
//Serial.println(throttle);
}
int read_steering() {
int steering = pulseIn(STEERING_PIN, HIGH, 20000);
steering = map(steering, 1000, 2000, 24, 169); //Servo values, calibrated according to my steering servo.
constrain (steering, 24, 169); //Make sure that the value stays within the disired boundaries.
//Serial.println("steering");
}
void move_forward(int val) {
analogWrite (MFORWARD_PIN, val);
digitalWrite (MBACKWARD_PIN, LOW);
Serial.print(" vooruit: ");
Serial.print(val);
}
void move_backward(int val)
{
val = abs(val);
analogWrite (MBACKWARD_PIN, val);
digitalWrite (MFORWARD_PIN, LOW);
Serial.print(" achteruit: ");
Serial.print(val);
}
void move_stop()
{
digitalWrite (MFORWARD_PIN, LOW);
digitalWrite (MBACKWARD_PIN, LOW);
}
void throttle_handle(int throttle) {
//Serial.print("throttle");
if (throttle > 40) {
move_forward(throttle);
}
if (throttle < -40) {
move_backward(throttle);
}
else {
move_stop();
}
}
void steering_handle(int steering) {
wheel.write(steering);
// Serial.println("steering:");
// Serial.print(steering);
}

Unused index:
Everywhere you loop over three values, whereas you only use two items in the array. So you'd better change all your sizes to 2 instead of 3, or you can define a NB_INPUT constant at the top of your source code, that you can change easily for more flexibility:
#define NB_INPUT 2
...
for (int i = 0; i<NB_INPUT; ++i) {
...
RXOK in setup():
your comment about arrays is justified, the first bug I can see in your code is that you read from the RXOK array, whereas you did not put any values in it. If you're sure that RXSG gets only zeroes from pulseIn() on the first pass of the Read RX values loop it can be ok, but I doubt it is. e.g.:
for (int i=0; i<3; ++i)
RXOK[i] = 0;
So you should put values in RXOK values in setup().
constant indexes in a for loop:
Then you map() the values from 1000->2000 to -255->255 for RXSG[0] and RXSG[1] inside the for loop, which will be done for the three iterations. I'm not sure what you want there, but if you want to do it for constant indexes, you'd better do it outside of the loop. But as you're checking a constraint on the -255->255 domain for each value of the iteration loop, I think you may want to do it on relative values:
PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255);
but it seems the domain is dependent on the index, so you may want to make a couple of defines at the top of your source code:
#define THROTTLE_IDX 0
#define STEERING_IDX 1
and put your map() in a if statement:
if (i == THROTTLE_IDX)
PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255);
elif (i == STEERING_IDX)
PWMSG[i] = map(RXSG[i], 1000, 2000, 24, 169);
# add a else statement if you need to do a map for the other values of the array
constrain(PWMSG[i], -255, 255)
general algorithm
I'm not sure you really need an array for your use case. You'd better keep a few variables around and have a better use of functions for your code to be readable and less bugprone:
#define THROTTLE_PIN 6
#define STEERING_PIN 7
#define WHEEL_PIN 8
#define MFORWARD_PIN 13
#define MBACKWARD_PIN 10
Servo wheel;
// sets up the arduino
void setup() {
Serial.begin(115200);
wheel.attach(WHEEL_PIN);
pinMode(THROTTLE_PIN, INPUT);
pinMode(STEERING_PIN, INPUT);
}
// input data handling
int read_throttle() {
int throttle = pulseIn(THROTTLE_PIN, HIGH, 20000);
return map(throttle, 1000, 2000, -255, 255);
}
int read_steering() {
int steering = pulseIn(STEERING_PIN, HIGH, 20000);
return map(throttle, 1000, 2000, 24, 169);
}
// output actions handling
void move_forward(int val) {
analogWrite(MFORWARD_PIN, val);
digitalWrite(MBACKWARD_PIN, LOW);
// Serial.print...
}
void move_backward(int val) {
analogWrite(MFORWARD_PIN, val);
digitalWrite(MBACKWARD_PIN, LOW);
// Serial.print...
}
void stop_motor() {
digitalWrite(MFORWARD_PIN, LOW);
digitalWrite(MBACKWARD_PIN, LOW);
}
void handle_throttle(int throttle) {
if (throttle > 40)
move_forward(throttle);
elif (throttle < -40)
move_backward(throttle);
else
stop_motor();
}
// general algorithm
void loop() {
int throttle = read_throttle();
delay(5);
handle_throttle(throttle);
}
There are more code duplication, but sometimes it is better to duplicate code than to make a code almost unreadable, and hard to debug while not offering any kind of flexibility/modularity. And here are a few other things I found in your code that should be corrected:
Naming convention: try to use good names for your functions (two letters variables, or dutch variables are not a good idea, I'm not english native and I always avoid to use my own language based names in code even for code I don't share, you never know who will read your code in 2 days, 2 months, or 2 years).
globals: Try to avoid using global variables as much as possible. Declare only constant in the global scope : const int foo = 1; or preprocessor defines #define foo 1, so that you do not spend too much of the little RAM space you have on your arduino. The only exception to that rule, which is very specific to arduino development, are objects (like Servo in your code) that you need to declare globally so you can set them up in the setup() function, and use them in the loop() function.
If I extrapolate on what you've written, you may want to add a handle_steering() function such as:
void handle_steering(int steering) {
if (steering > NN)
turn_left(steering);
elif (steering < NN)
turn_right(steering);
else
keep_straight();
}
and change the loop() to :
void loop() {
int throttle = read_throttle();
int steering = read_steering();
delay(5);
handle_throttle(throttle);
handle_steering(steering);
}
To make it a more general case of handling dynamically and flexibly a number of features, you could keep a few arrays:
PIN[]: containing the pins,
DOM_MIN[]: containing the minimum of the features' domain (for the map),
DOM_MAX[]: containing the maximum of the features' domain (for the map),
BOUND_MIN[]: containing the minimum boundaries (for the handle_steering condition),
BOUND_MAX[]: containing the maximum boundaries (for the handle_steering condition),
ACTION[]: containing the pointers to functions.
and then your algorithm would look like:
int read_input(int i) {
int value = pulseIn(PIN[i], HIGH, 20000);
return map(value, 1000, 2000, DOM_MIN[i], DOM_MAX[i]);
}
int handle_action(int i, int value) {
if (value > BOUND_MIN[i])
*(ACTION[i])(value);
elif (value < BOUND_MAX[i])
*(ACTION[i])(value);
else
*(ACTION[i])(-1);
}
void loop() {
for (int i=0; i<NB_INPUTS; ++i) {
int value = read_input(i);
delay(5);
handle_action(i, value);
}
}
but as you're still not comfortable with arrays (and I assume pointers as well), I would not recommend going further that way for the time being. First do it simple and make it work and then you could try to factorize it following the idea I'm exposing here. But you're making a software that is embedded, where the RAM is rare and the processing power is low, while your code space is cheap. So it's one of the few occasions where you'd better want to make a more redundant code that will stay in program space, whereas you want to manipulate as little symbols in the RAM. That's why I'm not showing you how the arrays are being declared/defined, and how to handle function pointers, because I don't think that solution (where you were heading) is the right way to do what you want.
Always remember, simpler is better!
HTH

Related

PWM for LED dimming unusual behavior

I made a function, where PWM signal is generated at the output (PORTD) without usage of PWM control registers inside PIC microcontroller (PIC18F452). In order to slowly dim LED connected at the output, I was trying to increase the time needed for pulse to advance from 0% of one period to 100% of one period of square wave, while having square wave frequency constant. Everything should go as planned, except that second parameter being passed into pwm function, somehow resets, when going from 655 to 666 (that is, when duty cycle is at 65%). After this event, value being passed to pwm function proceeds from 0. Where as it should not reset at transition from 655 to 656 but at transition from 1000 to 1001.
void main(void) {
TRISD = 0x00; //port D set as output
LATD = 0x00; //port D output set LOW
unsigned int width = 1000; // length of T_on + T_off
unsigned int j;
unsigned int res;
while(1){
for (j = 1; j <= width; j++){
res = (unsigned int)((j*100)/width);
pwm(&LATD, res);
}
}
return;
}
void pwm(volatile unsigned char *lat, unsigned int cycle){
if(cycle > 100){ // reset the "cycle"
cycle = 100;
}
unsigned int i = 1;
while(i<=(cycle)){ // T_on
*lat = 0x01;
i++;
}
unsigned int j = 100-cycle;
while(j){ // T_off
*lat = 0;
j--;
}
return;
}
As for the program itself, it should work like so:
second parameter passed into pwm function is the duty cycle (in %) which changes from 0 to 100
with variable "width" the time needed for duty cycle to advance from 0% to 100% is controlled (width = 100 represents fastest time and everything above that is considered gradually slower time from 0% to 100%)
expression ((j*100)/width) serves as step variable inside "while" loop inside pwm function:
if width = 100, step is increased every increment of "j"
if width = 1000, step is increased every 10 increments of "j",
etc.
PORTD is passed into function as its address, whereas in function pwm, this address is operated via pointer variable lat
As for the problem itself, I could only assume two possibilities: either data type of second parameter of function pwm is incorrect or there is some unknown limitation within PIC microprocessor.
Also, here are definitions of configuration bits (device specific registers) of PIC, located int header file included in this program: https://imgur.com/a/UDYifgN
This is, how the program should operate: https://vimeo.com/488207207
This is, how the program currently operates: https://vimeo.com/488207746
The problem is a 16 Bit overflow:
res = (unsigned int)((j*100)/width);
if j is greater then 655 the result of the calculation j*100 is greater 16 Bit. Switch this to 32 Bit. Or easier make your loop from 0...100 for res.
e.g.
for (res = 0; res <= 100; res++){
pwm(&LATD, res);
}

7 Segment Rfid Counter

I have rfid circuits. Im trying to add a counter with a 7 seven segment.
My seven segment giving random numbers like this.Photo
I think these numbers are opposite of my numbers. How can i solve this problem?
#include <16F887.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=4m,oscillator)
#define Dig1 PIN_D0
#define Dig2 PIN_D1
#define rfid PIN_D2
#define reset PIN_A1
#use fast_io(b)
#use fast_io(d)
char birler = 0, onlar = 0, sayi = 0;
void main()
{
int digit[10]={0b0111111,0b0000110,0b1011011,0b1001111,0b1101101,0b1111101,0b0000111,0b1111111,0b1101111};
set_tris_b(0x00);
output_b(1);
set_tris_d(0b11111100);
output_d(0b11111100);
output_b(0b11111100);
while(1)
{
output_b(digit[onlar]);
output_d(0b11111101);
delay_ms(5);
output_b(digit[birler]);
output_d(0b11111110);
delay_ms(5);
if(input(rfid) == 0)
{
sayi++;
birler = sayi%10;
onlar = sayi/10;
while(input(rfid) == 0)
{
output_b(digit[onlar]);
output_d(0b11111101);
delay_ms(5);
output_b(digit[birler]);
output_d(0b11111110);
delay_ms(5);
}
}
}
}
You really should consider isolating the display from your main loop, and eliminating the inline delays in your code. Pros are increased readability, easier maintenance, and eliminating delays for doing the actual work.
While preparing this response, I found out that your segments table is missing entries. Entry for '4' is missing.
The code below is far from complete. There is a digit missing in the LED segments table, you're using a switch that needs debouncing and it lacks a clock for non-blocking timers.
I've copy/pasted much of your app, and added comments...
#include <16F887.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=4m,oscillator)
#define Dig1 PIN_D0
#define Dig2 PIN_D1
#define rfid PIN_D2
#define reset PIN_A1
#use fast_io(b)
#use fast_io(d)
// never define const arrays on the stack.
static const int digit[10]= { 0b0111111, 0b0000110, 0b1011011, 0b1001111, /* missing '4' */ 0,
0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111 };
void display(unsigned char value)
{
static char tens = 0;
char dig = (tens) ? (value / 10) : (value % 10);
dig = digit[dig];
output_high((tens} ? Dig2 : Dig1);
output_b(dig); // <-- clobbers the high bit of B
output_low((tens} ? Dig1 : Dig2); // preventing other uses for it.
tens = !tens;
}
void main()
{
char sayi = 0;
output_b(1);
output_d(0b11111100);
output_b(0b11111100); // why set PORTB to 1 earlier? is that a bug?
set_tris_b(0x00); // always init tristate AFTER setting output
set_tris_d(0b11111100);
while(1)
{
display(sayi);
if(input(rfid) == 0) // debouncing needed. 30ms is a good delay for debouncing
{
sayi++; // what happens when we reach 100 ???
}
delay_ms(30); // in real-life, this should not be there.
// there are better ways to throttle a program,
// including going to sleep/idle.
}
}
I think these numbers are opposite of my numbers.
Check if your seven segment is common cathode or not, as it seems that the code is built for common cathode seven segment
And if it is common anode and it is your only choice, you can simply change the code to fit it by toggling all the bits in digit array, for ex zero will be 0b10000000
If your numbers are not appearing correctly, consider changing the digit array to
digit[] = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000};
and run each pattern for 5 seconds. That will tell you which bit is controlling which segment. What I've noticed about 7-segment displays from different manufacturers is that they don't always number the segments in the same way so 0b111111 may appear as 6 or 9: not necessarily 0.

Arduino problems with array

Hi I am working on a project lighting my house lights using an Arduino.
I have it working in a basic form, now I want to store the previous state of the light switch. I am using an array that stores the current state of the switch so it can be compared on the next loop. I have 7 switches, I have created it so one switch has the ability to turn on many lights, if required.
I need to store the previous state as the next part is to introduce web control the test project for this is already written
The strange thing is zones 7/8 work perfect. the other zones turn on, but don't turn off. When I turn on another switch a light may go off if it's switch is in the off position.
If I remove the condition for the previous state check all switches perfectly fine.
const int zone2[] = {8,13,0};
const int zone3[] = {11,0};
const int zone4[] = {7,0};
const int zone5[] = {9,0};
const int zone6[] = {12,0};
const int zone7[] = {6,0};
const int zone8[] = {14,0};
const int * zones[]={zone2,zone3,zone4,zone5,zone6,zone7,zone8};
int buttonState[] = {0,0}; // variable for reading the pushbutton status
int previousState[]={0,0,0,0,0,0,0,0}; // array for holding the previous state of the input button
void setup()
{
//initialize the output pins that will control lights
pinMode(6,OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9,OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13,OUTPUT);
pinMode(14,OUTPUT);
// initialize the pushbutton pin as an input:
//set all light switches to the same block ie pins 30 - 35
byte i;
//this loop sets all the 30-35pins as inputs
for (i=30;i< 37;i++) {
pinMode(i, INPUT);
digitalWrite(i,HIGH); // this makes it connect to the internal resistor
}
}
void loop()
{
int arrayPosition;
for (int z = 0; z < 7; ++z)//zero based array needs to be as many as there are zones!!!
{
buttonState[z] = digitalRead(z+30);
for (arrayPosition = 0;zones[z][arrayPosition] ; arrayPosition++)
{
if ((buttonState[z] == HIGH) ) && (previousState[z] == LOW )) {
// turn LED on:
digitalWrite(zones[z][arrayPosition],HIGH);
}
else if ((buttonState[z] == LOW) && (previousState[z] == HIGH )) {
// turn LED off;
digitalWrite(zones[z][arrayPosition],LOW);
}
}
//each light assigned to the zone has been turned on or off, now set previousstate
//the statement is here the inner loop has finsihed turning lights on or off that belong to that zone
previousState[z] = buttonState[z];
}
}
You allocate two elements to the array buttonState, but you are accessing seven:
[…]
int buttonState[] = {0,0};
[…]
for (int z = 0; z < 7; ++z)
{
buttonState[z] = digitalRead(z+30);
[…]
You should increase the number of elements in the buttonState array to be as many as you actually need.
It might be better to define the size of the arrays at a single place:
#define NUM_ZONES (7)
[…]
const int * zones[NUM_ZONES]={zone2,zone3,zone4,zone5,zone6,zone7,zone8};
int buttonState[NUM_ZONES] = {0,0,0,0,0,0,0};
int previousState[NUM_ZONES]={0,0,0,0,0,0,0};
[…]
for (int z = 0; z < NUM_ZONES; ++z)
[…]
This will also reveal that your previousState array is larger than needed (the compiler will complain that you have too many initialisers for that array). It is then important to re-use that constant everywhere instead of writing the magic number 7.

How can I replace delay() by millis()?

After a while, I get my final result I want but I can't use delay because I need different time for different strip, so I need to replace delay() by millis() in this code:
#include <FastLED.h>
#define NUM_LEDS1 10
#define NUM_LEDS2 6
#define DATA_PIN1 6
#define DATA_PIN2 7
CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN1>(leds1, NUM_LEDS1);
FastLED.addLeds<NEOPIXEL, DATA_PIN2>(leds2, NUM_LEDS2);
}
int dot_delay1[ ] = { 100,200,300,400,500,600,700,800,900,1000 };
int dot_delay2[ ] = { 100,200,300,400,500,600 };
void loop() {
for(int dot = 0; dot < NUM_LEDS1; dot++)
for(int dot = 0; dot < NUM_LEDS2; dot++)
{
leds1[dot] = CRGB::Blue;
leds2[dot] = CRGB::Blue;
FastLED.show();
leds1[dot] = CRGB::Black;
leds2[dot] = CRGB::Black;
delay( dot_delay1[ dot ] );
// this is where I need to put the second delay,
// but I can't put more then 1 delay.
// I need to refactor my code with millis() function instead of delay()
}
}
You can use non-blocking code patterns, which are executed in special frequencies or times. In the following, I give you an short example how you can replace a delay(1000) and a delay(5000) without blocking the main loop. In addition, you can check stackoverflow for similar posts (e.g. Pause without Delay() arduino).
// 1 sec. frequency
unsigned long interval=1000; // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.
// 5 sec. frequency
unsigned long interval1=5000; // the time we need to wait
unsigned long previousMillis1=0; // millis() returns an unsigned long.
void setup() {
//...
}
void loop() {
// other CMD's...
// replace delay(1000)
if ((unsigned long)(millis() - previousMillis) >= interval) {
previousMillis = millis();
// every first second
// ...
}
// other CMD's...
// replace delay(5000)
if ((unsigned long)(millis() - previousMillis1) >= interval1) {
previousMillis1 = millis();
// every fifth second
// ...
}
// other CMD's...
}
I see you're using NeoPixels! It just so happens that Adafruit has some great tutorials on using millis() and micros() for timing purposes instead of delay(). They also include good material on interrupts, if you're feeling ambitious and want to separate your timing from your main function entirely (a worthwhile undertaking, if you have the time and resources).
Part 1 (basics of using millis()):
https://learn.adafruit.com/multi-tasking-the-arduino-part-1/overview
Part 2 (introduces interrupts):
https://learn.adafruit.com/multi-tasking-the-arduino-part-2/overview
Part 3 (puts everything together):
https://learn.adafruit.com/multi-tasking-the-arduino-part-3/overview
Edit 1:
Alright, I edited your code, adding in a loop that checks for both delay periods to be done using millis(). I attempted to stick to the variable naming conventions that you've been using, for easy readability. There were also some other issues with your code syntax that I cleaned up. Make sure to effectively comment your code so that it's understandable, for yourself and for others!
Hopefully this works the way you want it to!
/*The goal of the sketch is to run multiple strip where each dot could be
controlled on/off one after the others but with different times on/off between each
pixel on each strip. All be independent and separate and automated and structured
already like FastLED library recommendation.*/
// Library include
#include <FastLED.h>
#define NUM_LEDS1 10
#define NUM_LEDS2 6
// Define pin (each strip be connected on)
#define DATA_PIN1 5
#define DATA_PIN2 6
// Declare some strip name and attribute (number of led per strip)
CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN1>(leds1, NUM_LEDS1);
FastLED.addLeds<NEOPIXEL, DATA_PIN2>(leds2, NUM_LEDS2);
}
int dot_delay1[] = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
int dot_delay2[] = {100, 200, 300, 400, 500, 600};
void loop() {
for (int dot1 = 0; dot1 < NUM_LEDS1; dot1++) {
for (int dot2 = 0; dot2 < NUM_LEDS2; dot2++) {
// LED turns blue
leds1[dot1] = CRGB::Blue;
leds2[dot2] = CRGB::Blue;
// Show LED status
FastLED.show();
// LED turns black
leds1[dot1] = CRGB::Black;
leds2[dot2] = CRGB::Black;
// Create timing variables
unsigned long previousMillis = millis();
unsigned long currentMillis = millis();
// Create boolean variables to monitor if the delays have triggered yet
bool delayFlag1 = false, delayFlag2 = false;
// Loop continuously
while (1) {
currentMillis = millis();
// If the first delay time has passed, delayFlag1 is true
if ((unsigned long)(millis() - previousMillis) >= dot_delay1[dot1]) {
delayFlag1 = true;
}
// If the second delay time has passed, delayFlag2 is true
if ((unsigned long)(millis() - previousMillis) >= dot_delay2[dot2]) {
delayFlag2 = true;
}
// If both delay times have passed (both delay flags are true), exit while loop
if ((delayFlag1 && delayFlag2) == true) {
break;
}
}
}
}
}
This new code should work, I've tested it and it works as expected on my machine.
As a side note, your original question was "How can I replace delay() by millis()?". This question has been answered both by myself and by the previous answer author, user3704293. In the future it may be helpful to separate your questions to get higher quality answers and to better serve those who are searching for answers to the same questions. Once your question is answered, as I hope this question is now, you should accept the answer that is the best for you.
Let me know if it all works out!
Edit 2:
To have LEDs change independently of each other, replace the loop() function in the previous code with this one.
void loop() {
// Create timing variable
unsigned long previousMillis = millis();
// Loop through all LEDs
for (int dot = 0; dot < NUM_LEDS1; dot++) {
// If the first delay time has passed, change first LED strip
if ((unsigned long)(millis() - previousMillis) >= dot_delay1[dot1]) {
leds1[dot - 1] = CRGB::Black;
leds1[dot] = CRGB::Blue;
}
// If the second delay time has passed, change second LED strip
if ((unsigned long)(millis() - previousMillis) >= dot_delay2[dot2]) {
leds2[dot - 1] = CRGB::Black;
leds2[dot] = CRGB::Blue;
}
// Show LEDs
FastLED.show();
}
// Turn last LED Black
leds1[9] = CRGB::Black;
}

Raspberry Pi, looping delay function

This is my code:
#include <wiringPi.h>
#include <stdio.h>
#define LED 18
#define IN 24
int main(void)
{
wiringPiSetupGpio ();
pinMode (LED, OUTPUT);
pinMode (IN, INPUT);
for (;;)
{
digitalWrite (LED, 1);
delay (2000);
digitalWrite (LED, 0);
delay (2000);
if (digitalRead (IN) == 1)
{
for (;;)
{
digitalWrite (LED, 1);
delay(500);
digitalWrite (LED, 0);
delay(500);
}
}
}
return 0;
}
I use a switch to go from the 2000 delay to the 500 delay. The problem is that when I press the switch it waits until the loop is over until it becomes faster. Same applies to vice versa. I need to write a function or a loop somewhere in my code that allows me to press the switch and immediately with no wait go to the slower/faster speed. I am coding this in C, on a raspberry pi using the wiring pi libraries, and gpio pin numbering.
First things first, that code as you've shown it will never deviate from a delay of 2000 simply because there's no way to exit from the initial for(;;) loop. That's probably the first thing you need to check and fix.
In terms of being able to end a delay early, you can do something like change:
delay (2000);
into:
for (i = 0; i < 2000; i += 10) {
delay (10);
if (digitalRead (IN) == 1)
break;
}
This basically exits the delay early if the switch changes, so that you'll never be waiting more than 10 time units (rather than up to 2000).
Just be aware that there may be an overhead to repeatedly calling delay. In other words, while delay(2000) may take very close to 2000 time units, two hundred calls to delay(10) may take a little more because of setup time for each call and so on.
In fact, you can probably greatly simplify your code by not using hard-coded values at all. Instead, you can have a single loop with minimal delay, with some internal controls which work out when and how to change the LED (i.e., not every time through the loop).
For example, something like this would do it. I haven't tested it since my Pi2 is still sitting in a box awaiting some time for me to play with it, but it should be pretty close:
#include <wiringPi.h>
#include <stdio.h>
#define LED 18
#define IN 24
#define RES 10
int main (void) {
int cycleTime, ledState, lastSwitch, currSwitch, timeLeft;
wiringPiSetupGpio ();
pinMode (LED, OUTPUT);
pinMode (IN, INPUT);
cycleTime = 2000; // Initial cycle time
ledState = 0; // and LED state.
lastSwitch = 0; // Previous switch state,
// Start infinite loop with first cycle time.
timeLeft = cycleTime;
for (;;) {
// Delay for minimal time and adjust time left.
delay (RES);
timeLeft = timeLeft - RES;
// Detect switch change.
currSwith = digitalRead (IN);
if (currSwitch != lastSwitch) {
// If so, store new state, change cycle time
// and force IMMEDIATE end of current cycle.
lastSwitch = currSwitch;
cycleTime = 2500 - cycleTime; // switch 500 <-> 2000
timeLeft = 0;
}
// Detect end of cycle.
if (timeLeft <= 0) {
// Toggle LED and start new cycle.
ledState = 1 - ledState;
digitalWrite (LED, ledState);
timeLeft = cycleTime;
}
}
}
Basically, you have a single loop but one which loops every ten time units rather than every 500 or 2000. You maintain a separate counter which decides when the LED should be flipped and the starting value for this counter depends on the current cycle time.
When the switch is flipped, that counter is zeroed so that it (almost) immediately changes to the next cycle.

Resources