I made a simple 1 button LED dimmer and I would like to have the LED go back to full brightness after the button has not been touched for a set amount of time. But the code I came up with does not seem to be working as I cannot dim the LED
int buttonPin = 12;
int LEDPin = 3;
int buttonVal;
int LEDbright = 0;
int dt = 500;
int fdt = 60000;
void setup() {
// put your setup code here, to run once:
pinMode(buttonPin, INPUT);
pinMode(LEDPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
static unsigned long whenButtonWasTouchedMs = 0;
buttonVal = digitalRead(buttonPin);
Serial.print("Button = ");
Serial.print(buttonVal);
Serial.print(", ");
delay(dt);
if (buttonVal == 1) {
LEDbright = LEDbright + 20;
whenButtonWasTouchedMs = millis();
}
Serial.println(LEDbright);
//
if (LEDbright > 255) {
LEDbright = 255;
delay(dt);
}
unsigned long afterButtonWasTouchedMs = millis() - whenButtonWasTouchedMs;
if (afterButtonWasTouchedMs >= 60000) {
LEDbright = 0;
analogWrite(LEDPin, LEDbright);
}
}
Your question doesn't seem to line up with how the code was written. It looks like you want to do the opposite (have the light get brighter when the button is held down, and then switch off 60 seconds after the button was released).
Here's the code I came up with to help with your stated problem:
int buttonPin = 12;
int LEDPin = 3;
int buttonVal;
int whenButtonWasTouched;
unsigned int LEDbright = 255;
int dt = 500;
int fdt = 60000;
unsigned long whenButtonWasTouchedMs = 0;
void setup() {
// put your setup code here, to run once:
pinMode(buttonPin, INPUT);
pinMode(LEDPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
//static unsigned long whenButtonWasTouchedMs = 0;
buttonVal = digitalRead(buttonPin);
Serial.print("Button = ");
Serial.print(buttonVal);
Serial.print(", ");
delay(dt);
if (buttonVal == 1) {
LEDbright = LEDbright - 20;
whenButtonWasTouchedMs = millis();
}
//
if (LEDbright < 20 || LEDbright > 255) { // The LEDbright > 255 part is because sometimes there can be an integer overflow if we don't keep this.
LEDbright = 0;
}
Serial.println(LEDbright);
unsigned long afterButtonWasTouchedMs = millis() - whenButtonWasTouched;
if (afterButtonWasTouchedMs >= 60000) {
LEDbright = 255;
}
analogWrite(LEDPin, LEDbright);
}
As you can see I changed it so that analogWrite is not in the if statement, it checks for integer overflows, and prints out the adjusted value for the led brightness. To make it grow brighter as the button is held and then switch off after 60 seconds just change the minus sign to a plus sign in the LEDbright adjustment line, and change some of the other values around.
int buttonPin = 12;
int LEDPin = 3;
int buttonVal;
unsigned int LEDbright = 0;
int dt = 500;
int fdt = 60000;
unsigned long whenButtonWasTouchedMs = 0;
void setup() {
// put your setup code here, to run once:
pinMode(buttonPin, INPUT);
pinMode(LEDPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
//static unsigned long whenButtonWasTouchedMs = 0;
buttonVal = digitalRead(buttonPin);
Serial.print("Button = ");
Serial.print(buttonVal);
Serial.print(", ");
delay(dt);
if (buttonVal == 1) {
LEDbright = LEDbright + 20;
whenButtonWasTouchedMs = millis();
}
if (LEDbright > 255) {
LEDbright = 255;
delay(dt);
}
Serial.println(LEDbright);
unsigned long afterButtonWasTouchedMs = millis() - whenButtonWasTouchedMs;
if (afterButtonWasTouchedMs >= 60000) {
LEDbright = 0;
}
analogWrite(LEDPin, LEDbright);
}
I'm currently working on a project that is mostly run on a Raspberry pi, but has tasks complete by microcontroller. Currently, my RPi is sending a string of integers separated by commas to a microcontroller (ESP 32 Thing plus), the microcontroller is then converting that into an intergern array and using those values to set the level of a PWM output. Simultaneously, the microcontroller is reading an analogue input and storing those values into another int array, this data needs to be sent back to the RPi. I've been trying for ages to convert this into a string to be sent back, which works for the most part using sprintf() and strcat(), but it only works when I have just the number values. It would be good to have commas separate the numbers, but as soon as I do that, I get a really weird out put and the numbers start changing from their actual value to "1792" or 44" and it cycles between them or if I us a float array then I get 6 variables correct and then the rest are changes to "512".
Its a lot to send but possibly better to see the whole thing.
#include <stdio.h>
// variables to hold, parse and manipulate data
const byte numChars = 64;
const byte stringLength = 255;
char receivedChars[1000];
char tempChars[1000];
char messageFromPC[stringLength] = {0};
int MyArray[] = {};
int LaserMeasurmentArray[200] = {};
char LaserMeasurmentString[] = "";
int BrakeArray [60] = {10,200,600,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,500,0,0,0};
int AccelleratingArray [60] = {10,200,600,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,500,0,0,0};
int TimeStamps[200] = {};
char TimeStampString = '0';
int i = 0;
int SizeOfArray = 0;
int MyArraySize = 0;
int Counter = 0;
int CounterLaser = 0;
//Clutch/Brake Setup
int ClutchPin = 33;
int BrakePin = 27;
int ButtonPin = 32;
int ButtonState = LOW;
int Delay = 10;
int PWM = 1023;
const int LaserPin = A0;
//Millis variables
unsigned long PreviousMillisAccel = 0;
unsigned long PreviousMillisLaser = 0;
unsigned long CurrentMillis = 0;
const int PeriodWrite = 8;
const int PeriodRead = 5;
//Action States
boolean newData = false;
boolean SendData = false;
boolean AccellerationInProgress = false;
boolean BrakingInProgress = false;
//============
void setup() {
Serial.begin(115200);
//ledcSetup(ledChannel, freq, resolution);
ledcSetup(1, 5000, 10);
ledcSetup(2, 5000, 10);
//ledcAttachPin(LED, ledChannel);
ledcAttachPin(ClutchPin, 1);
ledcAttachPin(BrakePin, 2);
pinMode(LaserPin, INPUT);
pinMode(ButtonPin, INPUT_PULLUP);
}
//============
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
//Serial.print(receivedChars);
//Serial.println();
parseData();
//showParsedData();
//ButtonPress();
ButtonState = HIGH;
while (ButtonState == HIGH) {
ButtonState = digitalRead(ButtonPin);
}//while
Serial.println();
Serial.print("Accellerating");
Serial.println();
PWMSignal();
Serial.println();
Serial.print("Deccellerating");
Serial.println();
PWMSignal2();
newData = false;
ButtonState = HIGH;
while (ButtonState == HIGH) {
ButtonState = digitalRead(ButtonPin);
}//While
SendReply();
}
}
//============
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= stringLength) {
ndx = stringLength - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData() { // split the data into its parts
i = 0;
String serialResponse = tempChars;
char buf[sizeof(tempChars)];
serialResponse.toCharArray(buf, sizeof(buf));
char *p = buf;
char *str;
while ((str = strtok_r(p, ",", &p)) != NULL && i < 1180 ){ // delimiter is the comma
MyArray[i] = atoi(str);
//Serial.println(str);
MyArraySize = i;
i++;
}//While
}//parseData
//============
void showParsedData() {
for(int i = 0; i < MyArraySize+1; i++){
Serial.print(MyArray[i]);
Serial.print(",");
}//For
Serial.println();
}
void PWMSignal(){
int Counter = 0;
CounterLaser = 0;
CurrentMillis = millis();
AccellerationInProgress = true;
while(AccellerationInProgress == true) {
CurrentMillis = millis();
if (Counter == 60){
AccellerationInProgress = false;
}//if
else if (CurrentMillis - PreviousMillisAccel >= PeriodWrite) {
ledcWrite(1, AccelleratingArray[Counter]);
//Serial.println(AccelleratingArray[Counter]);
Counter = Counter + 1;
PreviousMillisAccel = CurrentMillis;
}//else if
if (CurrentMillis - PreviousMillisLaser >= PeriodRead){
LaserMeasurmentArray[CounterLaser] = analogRead(LaserPin);
Serial.println(LaserMeasurmentArray[CounterLaser]);
TimeStamps [CounterLaser] = CurrentMillis;
PreviousMillisLaser = CurrentMillis;
CounterLaser = CounterLaser + 1;
}//if
}//While Accel
ledcWrite(1, 0);
}//PWMSignal
void PWMSignal2() {
int Counter = 0;
BrakingInProgress = true;
while(BrakingInProgress == true) {
CurrentMillis = millis();
if (Counter == 60){
BrakingInProgress = false;
}//if
else if (CurrentMillis - PreviousMillisAccel >= PeriodWrite) {
ledcWrite(2, BrakeArray[Counter]);
//Serial.println(BrakeArray[Counter]);
Counter = Counter + 1;
PreviousMillisAccel = CurrentMillis;
}//else if
if (CurrentMillis - PreviousMillisLaser >= PeriodRead){
LaserMeasurmentArray[CounterLaser] = analogRead(LaserPin);
Serial.println(LaserMeasurmentArray[CounterLaser]);
TimeStamps [CounterLaser] = CurrentMillis;
PreviousMillisLaser = CurrentMillis;
CounterLaser = CounterLaser + 1;
}//if
}//While Accel
ledcWrite(1, 0);
ledcWrite(2, 0);
}//PWMSignal2
void SendReply() {
//Serial.println("Laser Data");
//Serial.println(sizeof(LaserMeasurmentArray));
for (int i = 0; i<=200; i++){
Serial.println(LaserMeasurmentArray[i]);
}
for (int i = 0; i <= 200; i++){
int buff = LaserMeasurmentArray[i];
char str [7];
sprintf(str,"%u" ,buff);
strcat(LaserMeasurmentString,str);
strcat(LaserMeasurmentString, ",");
}
Serial.print(LaserMeasurmentString);
}//sendReply
If someone could point out what I am doing wrong or have misunderstood, that would be great, thank you.
I'm coding Arduino, but I'm confused about combining 2 sensors and 1 servo with a push button. I hope someone can help me.
I have made one by one the sensor coding and it works, but I want to combine them into one program.
// code void loop water temperatur sensor
void loop(void`{
sensors.requestTemperatures();
Celcius = sensors.getTempCByIndex(0);
Serial.print(Celcius);
Serial.println(" C ");
delay(1000);
}
// this code push button with servo
// code void servo with push button
void loop() {
if (digitalRead(pushButtonPin) == LOW) {
buttonPushed = 1;
Serial.println("Servo ON");
delay(1000);
}
if (buttonPushed) {
// change the angle for next time through the loop:
angle = angle + angleStep;
// reverse the direction of the moving at the ends of the angle:
if (angle >= maxAngle) {
angleStep = -angleStep;
if (type == 1) {
buttonPushed =0;
}
}
if (angle <= minAngle) {
angleStep = -angleStep;
if (type == 2) {
buttonPushed =0;
}
}
myservo.write(angle); // move the servo to desired angle
delay(100); // waits for the servo to get there
}
}
// Ph Sensor code
void loop(void) {
static unsigned long samplingTime = millis();
static unsigned long printTime = millis();
static float pHValue, voltage;
if (millis() - samplingTime > samplingInterval) {
pHArray[pHArrayIndex++] = analogRead(SensorPin);
if (pHArrayIndex==ArrayLenth)
pHArrayIndex=0;
voltage = avergearray(pHArray, ArrayLenth) * 5.0 / 1024;
pHValue = 3 * voltage + Offset;
samplingTime=millis();
}
if (millis() - printTime > printInterval) { //Every 800 milliseconds, print a numerical, convert the state of the LED indicator
Serial.print("Voltage:");
Serial.print(voltage, 2);
Serial.print(" pH value: ");
Serial.println(pHValue, 2);
digitalWrite(LED, digitalRead(LED) ^ 1);
printTime = millis();
}
}
double avergearray(int* arr, int number){
int i;
int max, min;
double avg;
long amount = 0;
if (number <= 0) {
Serial.println("Error number for the array to avraging!/n");
return 0;
}
if (number<5) { //less than 5, calculated directly statistics
for (i=0; i<number; i++) {
amount += arr[i];
}
avg = amount / number;
return avg;
} else {
if (arr[0] < arr[1]) {
min = arr[0];
max = arr[1];
} else {
min = arr[1];
max = arr[0];
}
for (i=2; i<number; i++) {
if (arr[i] < min) {
amount += min; //arr<min
min = arr[i];
} else {
if (arr[i] > max) {
amount += max; //arr>max
max = arr[i];
} else {
amount += arr[i]; //min<=arr<=max
}
} //if
} //for
avg = (double)amount / (number - 2);
} //if
return avg;
}
Your "Ph Sensor code" demonstrates how to do 2 things at different time intervals in one loop.
void loop() {
if (/* time is right to do thing 1 */) {
// do thing 1
}
if (/* time is right to do thing 2 */) {
// do thing 2
}
}
This is called a state machine. You can extend this logic to do 4 or more things in one loop.
Obviously you can't use delay as it blocks the entire loop, preventing other work from continuing. So you need to convert the first two loops into the structure similar to the one above. Then you will be able to merge all the loops into a single one.
So I have made a simple Arduino circuit for practice. I am able to start and stop the loop at any moment via a button. Now I want to make some sick led light sequences.
My initial thought is changing the delay_led1 function at the end of the loop. That way I am able to change the sequence when the loop ends.
I tried to do this with: interval_led1 + 300 (marked in my code with alot of /////////) at the end of the loop, but this doens't work.
How could I add milliseconds to the interval_led1 function via the loop?
const int led1 = 13;
const int led2 = 8;
const int led3 = 5;
const int button = 10;
int ledState_led1 = LOW; // ledState used to set the LED
int ledState_led2 = LOW;
int ledState_led3 = LOW;
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis_led1 = 0; // will store last time LED was updated
unsigned long previousMillis_led2 = 0;
unsigned long previousMillis_led3 = 0;
long interval_led1 = 500; // interval at which to blink (milliseconds)
long interval_led2 = 600;
long interval_led3 = 700;
boolean buttonstate = false;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(button, INPUT);
}
void loop() {
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis_led1 = millis();
unsigned long currentMillis_led2 = millis();
unsigned long currentMillis_led3 = millis();
bool current_state = digitalRead(button);
bool prev_buttonstate= false;
if(current_state==HIGH && current_state != prev_buttonstate) {
buttonstate = !buttonstate; //reverse buttonstate value
}
prev_buttonstate = current_state;
if(buttonstate==true)
if (currentMillis_led1 - previousMillis_led1 >= interval_led1) {
previousMillis_led1 = currentMillis_led1;
if (ledState_led1 == LOW) {
ledState_led1 = HIGH;
} else {
ledState_led1 = LOW;
}
digitalWrite(led1, ledState_led1);
////////interval_led1 + int(3000); ///////////////////
}
if(buttonstate==true)
if (currentMillis_led2 - previousMillis_led2 >= interval_led2) {
previousMillis_led2 = currentMillis_led2;
if (ledState_led2 == LOW) {
ledState_led2 = HIGH;
} else {
ledState_led2 = LOW;
}
digitalWrite(led2, ledState_led2);
}
if(buttonstate==true)
if (currentMillis_led3 - previousMillis_led3 >= interval_led3) {
previousMillis_led3 = currentMillis_led3;
if (ledState_led3 == LOW) {
ledState_led3 = HIGH;
} else {
ledState_led3 = LOW;
}
digitalWrite(led3, ledState_led3);
}
}
Did you mean to have:
Interval_led = interval_led1 + 3000;
Where you actually assign a new value to that variable?
I have this problem where I try to set an output pin high for a set time and times.
I do the call with hapticFeedback(1000, 2, 1);
the variables are defined as
unsigned long hapticPreviousMillis = 0;
int hapticState = LOW;
int oneshotHaptic = 0;
here is the function. For some reason I only get the pin set HIGH and not the blinks and LOW
void hapticFeedback(int activeLength, int repeats, int oneshotHaptic) {
if (oneshotHaptic == 1) {
for (int x = 0; x <= repeats; x++) {
unsigned long currentMillis = millis();
if (currentMillis - hapticPreviousMillis >= (unsigned long)activeLength) {
hapticPreviousMillis = currentMillis;
if (hapticState == LOW) {
hapticState = HIGH;
}
else {
hapticState = LOW;
}
digitalWrite(haptic, hapticState);
}
}
}
oneshotHaptic = 0;
}
So I figured it out and if anyone else is looking for this here is what I came up with. It might not be the smoothest of code but it does what I intended it to do
in the loop I have
if (setOneshotHaptic == 1) {
hapticFeedback(activeLength);
}
and the haptic function look like this
void hapticFeedback(int activeLength) {
unsigned long currentMillis = millis();
if (currentMillis - hapticPreviousMillis >= (unsigned long)activeLength) {
hapticPreviousMillis = currentMillis;
if (x == repeats) {
setOneshotHaptic = false;
hapticState = HIGH;
x = 0;
}
if (hapticState == LOW) {
hapticState = HIGH;
x++;
}
else {
hapticState = LOW;
}
digitalWrite(haptic, hapticState);
}
}
whenever i like to have haptic feedback i can define the following vars
setOneshotHaptic = true;
repeats = 3;
activeLength = 1000;
When the number of repeats has been reached I lay down the oneshot, force the output to high for it to be low by the routine and finally reset my repeat counter.
There might be nicer ways to do this. However I couldn't find them and this works for me....