How to turn a LED-Strip off after if condition - led

\
I'm working on code have that simulate Knight rider leds. I want to control Led via bluetooth as i can switch off.
but i tried several things but doesn't work .
any help.
*/I'm working on code have that simulate Knight rider leds. I want to control Led via bluetooth as i can switch off.
but i tried several things but doesn't work .
any help
code:
#include "BluetoothSerial.h"
#include <Adafruit_NeoPixel.h>
#define N_LEDS 8
#define PIN 23
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB +
NEO_KHZ800);
BluetoothSerial ESP_BT;
int incoming;
int r;
int pos = 0, dir = 1;
void setup() {
strip.begin();
Serial.begin(9600);
ESP_BT.begin("ESP32_LED_Control");
Serial.println("Bluetooth Device is Ready to Pair");
}
void loop() {
strip.setPixelColor(pos - 2, 0x100000); // Dark red
strip.setPixelColor(pos - 1, 0x800000); // Medium red
strip.setPixelColor(pos , 0xFF3000); // Center pixel is brightest
strip.setPixelColor(pos + 1, 0x800000); // Medium red
strip.setPixelColor(pos + 2, 0x100000); // Dark red
strip.show();
delay(85); // control speed
for (r=-2; r<= 2; r++) strip.setPixelColor(pos+r, 0);
pos += dir;
if (pos < 0) {
pos = 1;
dir = -dir;
} else if (pos >= strip.numPixels()) {
pos = strip.numPixels() - 2;
dir = -dir;
}
if (ESP_BT.available()) //Check if we receive anything from Bluetooth
{
incoming = ESP_BT.read(); //Read what we recevive
Serial.print("Received:"); Serial.println(incoming);
}
if (incoming == 48)
{
//Should put here code that works on stop strip led//
ESP_BT.println("LED turned OFF");
}
}

To turn off all LEDs I would do something like:
/**
* Turn off all LEDs
*/
void allBlack()
{
for (uint16_t indexPixel = 0; indexPixel < N_LEDS; indexPixel++)
{
strip.SetPixelColor(indexPixel, 0x000000);
}
strip.show();
}
I know is maybe not the scope of this question, but I recommend to test this library:
https://github.com/Makuna/NeoPixelBus
Since it has a lot of good examples and it would be in my opinion a lot better not to use delay but give a certain time like it's shown on Makuna examples to have more control over the animation.
I also have another animation examples in this small project that is triggered by UDP commands.

Related

time between two edges pic 18f4550

I would like to calculate the time interval between two rising edges of two different signals using the two CCP modules from pic 18f4550.
The idea of ​​calculation is illustrated in the following figures.
The simulation works fine, but my electrical circuit is not. I don't know if there is something wrong with my code. If anyone has an answer or a clue to fix this, I will be grateful! And if you have any questions, please feel free to ask.
#pragma config FOSC = INTOSC_EC
#define _XTAL_FREQ 8000000
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "LCD_8bit_file.h"
#include <string.h>
unsigned long comtage, capt0, x;
char DEPHASAGE[20];
char pulse[20];
float period, dephTempo, deph, phi;
void main()
{
IRCF0 = 1; /* set internal clock to 8MHz */
IRCF1 = 1;
IRCF2 = 1;
LCD_Init();
LCD_String_xy(0, 1, "Dephasage[rad]");
T3CONbits.RD16 = 1;
T3CKPS0 = 0;
T3CKPS1 = 0;
TMR3CS = 0;
TMR3IF = 0;
while (1)
{
CCP2CON = 0b00000101;
CCP1CON = 0b00000101;
PIR2bits.CCP2IF = 0;
PIR1bits.CCP1IF = 0;
TMR3ON = 0;
TMR3 = 0;
if (PIR1bits.CCP1IF == 1) {
TMR3ON = 1;
while (!PIR2bits.CCP2IF);
comtage = TMR3;
dephTempo = (((float)comtage / 30.518) / 65536);
sprintf(pulse,"%.3f ", dephTempo);
LCD_String_xy(0, 0, "Dephasage : ");
LCD_String_xy(2, 9, pulse);
}
}
}
When you test a schematic using a real circuit, other issues will appear, like capacitive and resistive parasitics and that will after the timings. Also, can have jitter noise. If you a have an oscilloscope, try to figure out if there is too much noise. Try do add a pull-down/pull-up on those lines, make sure you have good ground connection. But after looking for your code, you should take an approach similar to CTC: You make fast samples of your input signal and then you check your sampled array, if there is more one than zeros, you caught an edge trigger.
I have a better scenario for your application to implement. But first let's talk about the bad practices in your code.
In your main while loop you setup the CCP modules:
CCP2CON = 0b00000101;
CCP1CON = 0b00000101;
PIR2bits.CCP2IF = 0;
PIR1bits.CCP1IF = 0;
TMR3ON = 0;
TMR3 = 0;
You better do this before the program enters to the infinite while loop.
You handle the timer reads directly while the CCP module captures its value in which the edge you configured it to capture.
comtage = TMR3;
I don't see that you configure the CCP pins as inputs. You have to configure them as inputs by setting the corresponding TRIS bits in order to have them working properly.
So the structure of my recommended scenario would be something like this:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "LCD_8bit_file.h"
#include <string.h>
unsigned long comtage, capt0, x;
char DEPHASAGE[20];
char pulse[20];
float period, dephTempo, deph, phi;
/******************** Utility funcs ********************/
void setupSysClock() {
IRCF0 = 1; /* set internal clock to 8MHz */
IRCF1 = 1;
IRCF2 = 1;
}
void setupCCP1withTMR1() {
CCP1CON = 0b00000101;
PIR1bits.CCP1IF = 0;
TRISCbits.TRISC2 = 1; // set CCP1 pin as input
}
void setupCCP2withTMR3() {
CCP2CON = 0b00000101;
PIR2bits.CCP2IF = 0;
// T3 goes for CCP2 and CCP1, PS 1:1, internal CS
T3CON = (1 << T3CCP2) | (0 << T3CKPS1) | (0 << T3CKPS0) | (1 << T3CCP1) | (0 << TMR3CS);
TMR3 = 0;
// In config bits you must choose RC1 pin for the CCP2 if necessary although it so by default
TRISCbits.TRISC1 = 1 // set CCP2 pin as input
}
void rearm() {
CCP1CON = 0x5
CCP2CON = 0x5
PIR1bits.CCP1IF = 0;
PIR2bits.CCP2IF = 0;
TMR3 = 0;
TMR3ON = 1;
}
void suspend() {
CCP1CON = 0;
CCP2CON = 0;
}
void main()
{
setupSysClock(); // setu internal clock
setupCCP1withTMR1(); // setup CCP1 for capture mode
setupCCP2withTMR3(); // setup CCP1 for capture mode with TMR3
LCD_Init();
LCD_String_xy(0, 1, "Dephasage[rad]");
while (1)
{
while(!CCP2IF); // Wait for the second rising edge
// Event has occured process, first make sure that the CCP1 rised first
if(!CCP1F) {
// An invalid sequence occured ignore and rearm. Note that the sequence of signals is important.
rearm();
continue;
}
/* The sequence is correct let's process the event. Here you will have
two captured value in CCPR1 and CCPR2 registers. First one is the captured value of the T3 when the first rising event occured. Second one is the captured value of the T3 when the second rising event occured. You have to get the delta of the two captured values first. This delta value is the elapsed ticks between the two discrete rising input signals. This is what the capture hardware is made for ;)
Now first we shuld suspend the CCP modules to avoid unwanted captures
while we process the previous value. Because if another capture occures
before we process the previous value, the new capture value will be
overwritten over the old value that we need for computation.
*/
suspend(); // suspend the CCP modules while processing
uint16_t timeDelta = CCPR2 - CCPR1; // Calculate the difference
dephTempo = (((float)timeDelta / 30.518) / 65536);
sprintf(pulse,"%.3f ", dephTempo);
LCD_String_xy(0, 0, "Dephasage : ");
LCD_String_xy(2, 9, pulse);
// Now that we finished processing we can rearm the CCP for new captures
rearm();
}
}
I wrote this code in an editor and haven't compiled in MPLAB. So you must compile and test the code. You can give me a feedback for me to help further.
One important thing to note: If the amount of time between two signals is large, you must either increment the prescaler of Timer3 or you must use a complementary variable for TMR3 register in case it overflows.

How to determine button press duration with wiringpi in C

For a aspberry pi project I have buttons connected to GPIO and I want to take different actions depending on how long a button has been pressed. The following python code (extract) is working as expected:
on_button2(channel):
t1 = time.time()
# Wait for button release
while GPIO.input(channel) == 0:
pass
duration = time.time() - t1
print "duration: %f" % (duration)
if duration > 0.75:
mpd_client.previous()
else:
mpd_client.next()
GPIO.add_event_detect(BUTTON2_PIN, GPIO.FALLING, callback=on_button2, bouncetime=700);
I would like to convert this into a C program (don't ask why, I really don't like python and I'm much more familiar with C, so I'd like to do it in C)
Trying to convert this to C with wiringPi, I came up with this, but it is not working as expected:
unsigned long btn2_t0;
static void on_button_2_pressed() {
unsigned long duration, t1;
int level;
level = digitalRead(BUTTON_2_PIN);
// Debounce button
t1 = millis();
if (t1 - btn2_t0 < 700) {
return;
}
btn2_t0 = t1;
// Wait for button being released
while (digitalRead(BUTTON_2_PIN) == LOW) {
delay(100);
}
duration = millis() - t1;
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
int main() {
// Setup WiringPi Lib
wiringPiSetupGpio();
pinMode(BUTTON_2_PIN, INPUT);
// Register callbacks on button press
wiringPiISR(BUTTON_2_PIN, INT_EDGE_FALLING, on_button_2_pressed);
for (;;) {
delay(500);
}
return 0;
}
It seems that the loop that should wait for button release is not being executed or that the while-condition is always true, and thus, duration always is zero.
Is the digitalRead(BUTTON_2_PIN) function equivalent to the GPIO.input(channel) in the python code at all?
If somebody could point me in the right direction on how to detect button press (software-debounced) and measure the duration of the button press in C.
Thanks a lot.
EDIT: Working solution
After playing around a lot and with the help of Francesco Boi I came around with a working solution, although I do not really understand why the compare logic with HIGH / LOW is swapped compared to the python code (I thought that the button press will cause the pin to FALL to LOW and releasing it would RAISE it to HIGH ...)
static void on_button_2_pressed() {
unsigned long duration;
static unsigned long button_pressed_timestamp;
int level = digitalRead(BUTTON_2_PIN);
if (level == HIGH) { // Why HIGH ?!?
button_pressed_timestamp = millis();
}
else {
duration = millis() - button_pressed_timestamp;
button_pressed_timestamp = millis();
if (duration < 100) {
// debounce...
return;
}
else if (duration < 700) {
syslog(LOG_NOTICE, ">> NEXT\n");
}
else if (duration < 3000) {
syslog(LOG_NOTICE, "<< PREV\n");
}
else {
syslog(LOG_NOTICE, "!! REBOOT\n");
}
}
}
int main() {
...
wiringPiISR(BUTTON_2_PIN, INT_EDGE_BOTH, on_button_2_pressed);
...
}
First of all you are reading the value of the pin into level then in the while loop you are re-reading it: why is that? Can't you do something like:
// Wait for button being released
while (level == LOW) {
delay(100);
}
?
Also don't you want to reassign the btn2_t0 = t1; even when the time was smaller than 700 ms? Like:
t1 = millis();
if (t1 - btn2_t0 < 700) {
btn2_t0 = t1;
return;
}
The behaviour depends on how you built your electronic circuit: is the button-press suppose to make the pin high or low? Be sure about the behaviour is the one you are expecting by either connecting a led and a resistor or using a Voltmeter.
However since your Python code worked I am assuming the electronic is correct and your algorithm too.
Be sure of course you are pressing the button long enough. Add some prints to your code to understand which branches it is executing because when there is electronic involved it is difficult to understand only by the code.
While waiting for news from you, in my opinion is better to do the following: define the callback as: INT_EDGE_BOTH so that it got called when the bottom is pressed and when the button is released. You can keep the time elapsed with a static variable.
void yourCallback()
{
unsigned long ela, t;
int level = digitalRead(BUTTON_2_PIN);
static unsigned long button_pressed_timestamp;
//if button pressed:
if(level==LOW)
{
//start counting
button_pressed_timestamp = millis();
}
else //button released
{
duration = millis()-button_pressed_timestamp;
button_pressed_timestamp = millis(); //just to be sure....
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
}

Arduino Switch to Turn a Relay timer

Briefly: I would like to turn on a relay for 30 seconds, after I toggle a switch on.
I'm trying to do a blinds automation at home.
I have a simple ON-OFF-ON switch, attached to an Arduino connected to Relays.
I want to turn on Relay#1 for a maximum of 30 seconds if I toggle the switch down from center. In other words, relay turns on when I switch, and when timer reaches 30 seconds relay turns off.
similarly I want to turn on Relay#2 for exactly 30 seconds if I toggle the switch up from center
And when I switch back to center, I would like the timer to reset.
I could not figure out how. Could anyone help?
I have been trying to use elapsedMillis library for this, which is a nice library that helps me avoid using Delays:
http://playground.arduino.cc/Code/ElapsedMillis
However even though I could work the relays without the 30 second limitation, I couldn't figure out the code to end working of the relays. Here is my current code:
#include <elapsedMillis.h>
#define RELAY_ON 0
#define RELAY_OFF 1
#define RELAY1_TURNS_ON_BLINDS 5
#define RELAY2_SHUTS_DOWN_BLINDS 6
#define shutswitch A0
#define openswitch A1
bool LocalCommandToOpen;
bool LocalCommandToShut;
void setup() ////////SETUP////////
{
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
pinMode(RELAY1_TURNS_ON_BLINDS, OUTPUT);
pinMode(RELAY2_SHUTS_DOWN_BLINDS, OUTPUT);
pinMode(shutswitch, INPUT);
pinMode(openswitch, INPUT);
} ////SETUP
void loop() { ///////LOOP
if (digitalRead(shutswitch) == 1)
{
LocalCommandToOpen = 1;
}
else
{
LocalCommandToOpen = 0;
}
if ( digitalRead(openswitch) == 1)
{
LocalCommandToShut = 1;
}
else
{
LocalCommandToShut = 0;
}
unsigned int CloseInterval = 14000;
elapsedMillis timeElapsedSinceCloseButtonPush = 0;
unsigned int OpenInterval = 14000;
elapsedMillis timeElapsedSinceOpenButtonPush = 0;
//MANUAL SWITCH OPERATION
if ( LocalCommandToShut == 1 )
{
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_ON);
}
else
{
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
}
//MANUEL DUGME ILE ACMA
if ( LocalCommandToOpen == 1)
{
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_ON);
}
else
{
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
}
delay(500);
} /////////////////LOOP////////////////////////////////////
One suggestion here is to use a "state machine", so that upon a switch transition, you get 'State 1'; in that state, a timer starts, and puts you in 'State 2'. In 'State 2', you check the time, and if it goes beyond X seconds, you go to 'State 3'. You can monitor the transition of a switch from low to high (or high to low), and use this to reset the state of the system.
A sample bit of code gives you an idea of how to implement this. The variable 'SystemState' is an integer, and SYSTEM_ABORT, SYSTEM_IDLE, etc. are constants.
The beauty of this is that the transition is easy to figure out. For example, if you are in the SYSTEM_WAIT state, the only thing you are looking for is the time to be greater than 5 seconds. Also, you can look at input transitions or values to set states (like SystemStopButton == 0, to set the state to be 'SYSTEM_ABORT').
// SystemStopButton is an input
void SystemStateMachine(void)
///////////////////////////////////////////////////////////////////////////////////////////
{
if (SystemStopButton == 0)
{
SystemState = SYSTEM_ABORT;
}
switch (SystemState)
{
case SYSTEM_IDLE:
{
RunPinState = OFF;
StopPinState = OFF;
if (SystemRunButton == 0)
{
SystemState = SYSTEM_START;
ShowStep();
}
break;
}
case SYSTEM_START:
{
StandardMessage = "START ";
RunPinState = ON;
StopPinState = OFF;
SystemState = SYSTEM_WAIT;
ShowStep();
break;
}
case SYSTEM_WAIT: // wait for 5 seconds
{
StandardMessage = "WAIT ";
if ((CurrentMillis - StateStepTimeMillis) > 5000)
{
SystemState = SYSTEM_RETRACT;
ShowStep();
}
break;
}
case SYSTEM_RETRACT: //
{
StandardMessage = "RETRACT";
/* motor stuff goes here... */
if ((CurrentMillis - StateStepTimeMillis) > 5000)
{
SystemState = SYSTEM_ADVANCE_TAPE_WAIT
ShowStep();
}
break;
}
// etc. etc. etc.
case SYSTEM_ABORT: //
{
StandardMessage = "ABORT";
/* motor stop stuff goes here... */
SystemState=SYSTEM_IDLE;
break;
}
default:
{
break;
}
}
}
void ShowStep(void)
/////////////////////////////////////////////////////////////////////
// show step and set time so we can keep track of time in each step
{
Serial.print("SystemState = ");
Serial.println(String(SystemState));
SetStepTime();
}
void SetStepTime(void)
/////////////////////////////////////////////////////////////////////
{
StateStepTimeMillis = CurrentMillis;
}
You might use a state machine; this makes things a bit easier to follow.
Similar to:
Arduino Switch to Turn a Relay timer
A nice discussion of state machines is here:
Complicated state transitions: best practices

Arduino Motor Ramp

I need some help with my arduino ramp motor code.
I am making a remote control robot. The remote has one button.
If the button is high: The motor should gradually increase its speed using pwm (Starting with pwm=0).The time period from standstill speed to maximum speed should be 1 second. Once it has reached maximum speed it should maintain the maximum speed (pwm=255).
The moment the button is released the motor should gradually decrease from the current speed to a complete standstill.
So far I have managed to write the ramp up and maintain speed part of the code; the code doesn't include the button part.
int motor;
int motorpwm=11;
int x=1;
int i;
void setup()
{
pinMode(11,OUTPUT);
Serial.begin(9600);
}
void loop()
{
for(int i=0;i<256;i=i+x)
{
analogWrite(motorpwm,i);
Serial.println(i);
if(i==255)
{
x=0;
Serial.println("PWM is maximum");
}
}
}
Please include the complete code including the button control part of the code.
I do not assure you if this is bug-free but you can try this and post your restults here, so that I can debug it for you. Here you go:
int motor;
int motorpwm = 11;
int x = 1;
int i;
int pwmValue;
void setup()
{
pinMode(11, OUTPUT);
pinMode(2, INPUT); //Button connected to Vcc and pulled down using a 10k resistor.
Serial.begin(9600);
}
void loop()
{
if (digitalRead(2)) //if button is pressed it will read High signal
{
if (pwmValue <= 255)
{
analogWrite(motorpwm, pwmValue++);
Serial.print("Going Up with value: ");
Serial.println(pwmValue);
}
else
{
Serial.println("PWM is maximum");
}
}
else
{
if (motorpwm > 0)
{
analogWrite(motorpwm, pwmValue--);
Serial.print("Going down with value: ");
Serial.print(pwmValue);
}
else
{
Serial.println("PWM is minimum");
}
}
}

OpenCV - Video playback is slow if slider updates its position while playing

I have picked up 'Learning OpenCV' and have been trying some of the code examples/exercises. In this code snippet, I want to get the slider to update its position with each video frame change, but for some reason it is slowing down the video playback speed.
The slider is updating the position during video playback using cvSetTrackbarPos() function but it is making the playback very slow.
#include <cv.h>
#include <highgui.h>
using namespace std;
int g_slider_position = 0;
CvCapture *g_capture = NULL;
void onTrackbarSlide(int pos)
{
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
int main(int argc, char *argv[])
{
if(argc<2)
{
printf("Usage: main <video-file-name>\n\7");
exit(0);
}
// create a window
cvNamedWindow("Playing Video With Slider", CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture(argv[1]);
int frames = (int) cvGetCaptureProperty(g_capture, \
CV_CAP_PROP_FRAME_COUNT);
if(frames !=0)
{
cvCreateTrackbar("Slider","Playing Video With Slider", \
&g_slider_position,frames, onTrackbarSlide);
}
IplImage* frame = 0;
while(1)
{
frame = cvQueryFrame(g_capture);
if(!frame)
{
break;
}
cvShowImage("Playing Video With Slider", frame);
cvSetTrackbarPos("Slider","Playing Video With Slider", \
g_slider_position+1); //Slowing down playback
char c= cvWaitKey(33);
if(c == 27)
{
break;
}
}
// release the image
cvReleaseImage(&frame );
cvReleaseCapture(&g_capture);
// Destroy Window
cvDestroyWindow("Playing Video With Slider");
return 0;
}
This is an inefficiency in how opencv displays trackbars (the same problem occurs even if you don't update the slider, and in case when you refer to non-changing variable outside the processing loop).
A workaround might be to display the trackbar in a separate window.
Line char c= cvWaitKey(33); have problem.
It is in while(1) and every time it takes 33 milisecond to Wait for a pressed key.Make this number lesser.
EDITED LATER:
Make change as shown below
void onTrackbarSlide(int pos)
{
pos = g_slider_position;
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
The problem is that every time You call cvSetTrackbarPos("Slider","Playing Video With Slider", g_slider_position+1); callback onTrackbarSlide changing the video position another time and slowing down the program flow.
The way I find out to avoid that is with a flag. It tells the callback if the change in the Trackbar is produced by the normal update flow or is produced by You.
int g_slider_position = 0;
int g_update_slider = 0;//flag
CvCapture *g_capture = NULL;
void onTrackbarSlide(int pos)
{
if (!g_update_slider)//if not changed by the video flow
{
cvSetCaptureProperty(
g_capture,
CV_CAP_PROP_POS_FRAMES,
pos
);
}
}
void updateSlider(int pos)
{
g_update_slider = 1; //Changed by the video flow
cvSetTrackbarPos("Position", "Example3", pos);
g_update_slider = 0; //Returns the flag when the change is performed
}
In the main I call for updateSlider instead of cvSetTrackbarPos.

Resources