I have written a code that detects a button press, first time the button is pressed a LED glows and when next time it is pressed , the LED should switch off, in the same way if third time it is pressed the LED should again glow.
The problem is , the controller is able to detect the button press but instead of switching on the LED for long time, it just momentarily switches it ON then it again switches OFF. And further button presses are not detected.
Below is the code:
#include <avr/io.h>
#include <avr/delay.h>
void glow();
void off();
void switchScan();
int main()
{
DDRA=0x02; // 0000 0010 --> BIT 0=connected to switch whose other pin is connected to ground,, and BIT 1 is connected to LED with other pin of led connected to ground
PORTA=0x01; // 0000 0001---> Switch Input pulled up and LED output pulled down
while(1)
{
switchScan();
}
return 0;
}
void glow()
{
PORTA=PORTA|(1<<1);
}
void off()
{
PORTA=PORTA&(~(1<<1));
}
void switchScan()
{
static int counter=0;
if(~(PINA & 0x01))
{
counter++;
if(counter < 2)
glow();
else
{
counter--;
off();
}
}
}
The logic in your switchScan() function is flawed. glow() will only be executed one single time. See code comments:
void switchScan() {
static int counter=0;
if (~(PINA & 0x01)) {
counter++;
// 1st button press: counter will be 1
// 2nd and all following button presses: counter will be 2
if (counter < 2)
// can only be called once!
glow();
else {
// counter will always go from 2 to 1 at this point
counter--;
off();
}
}
}
However, you should also consider the de-bouncing that Brett mentioned in the comments.
Related
.
.
.
void setup() {
/*
RGB LED 입출력설정
*/
pinMode(R_LED_PIN, OUTPUT);
pinMode(G_LED_PIN, OUTPUT);
pinMode(B_LED_PIN, OUTPUT);
lcd.init(); // LCD 초기화
lcd.backlight(); // LCD 백라이트 켜기(화면 밝아짐)
lcd.setCursor(2,0); // 커서 (2,0)
lcd.print("*INTERRUPT*"); // 글자출력
delay(500);
attachInterrupt(digitalPinToInterrupt(BUTTONPIN), button, FALLING);
/* 인터럽트 설정(아두이노 3번 핀, button 함수 호출, 모드 FALLING */
}
void loop() {
/*
led_color 함수에 Red, Green에 무작위 값과 Blue에는 0을 인자로 전달
delay를 0~99 사이의 무작위 값으로 설정
*/
led_color(random(256), random(256), 0);
int Blue = 0;
delay(random(100));
.
.
.
I can't resolve the problem like a title
in the interrupt zone: attachInterrupt(digitalPinToInterrupt(BUTTONPIN), button, FALLING);
Arduino uno error makes me crazy!!!!!!
Please help me...
You have not shared the whole code but for your understanding I have written code in place of button you have to provide a function checkSwitch.
const byte ledPin = 13;
const byte buttonPin = 2;
// Boolean to represent toggle state
volatile bool toggleState = false;
void checkSwitch() {
// Check status of switch
// Toggle LED if button pressed
if (digitalRead(buttonPin) == LOW) {
// Switch was pressed
// Change state of toggle
toggleState = !toggleState;
// Indicate state on LED
digitalWrite(ledPin, toggleState);
}
}
void setup() {
// Set LED pin as output
pinMode(ledPin, OUTPUT);
// Set switch pin as INPUT with pullup
pinMode(buttonPin, INPUT_PULLUP);
// Attach Interrupt to Interrupt Service Routine
attachInterrupt(digitalPinToInterrupt(buttonPin),checkSwitch, FALLING);
}
void loop() {
// 5-second time delay
Serial.println("Delay Started");
delay(5000);
Serial.println("Delay Finished");
Serial.println("..............");
}
This is my first stack overflow post (long time lurker), so sorry in advance if this question isn't well worded.
I'm trying to make a kernel module to emulate keypresses when a user presses a button, and using http://www.staerk.de/thorsten/My_Tutorials/Writing_Linux_kernel_modules as an example.
It does simulate a keypress when the module is initialized, but when I send an interrupt and try to run the same code the entire virtual machine freezes.
Here's snippits of my code:
static void got_char(struct work_struct *taskp)
{
struct myprivate *myp = container_of(taskp, struct myprivate, task);
if ((myp->scancode == 0x01) || (myp->scancode == 0x81))
{
printk ("You pressed Esc !\n");
println ("Pressed ESC ! \n");
ch=65;
tty_insert_flip_char(tty, ch, 0);
con_schedule_flip(tty);
}
else if (myp->scancode == 0x1D) {
printk ("You pressed Ctrl!\n");
}
else {
printk("Scancode = %d", myp->scancode);
}
}
irq_handler_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
static int initialised = 0;
/*
* Read keyboard status
*/
myp->scancode = inb(0x60);
if (initialised == 0) {
INIT_WORK(&myp->task, got_char);
initialised = 1;
}
else {
PREPARE_WORK(&myp->task, got_char);
}
schedule_work(&myp->task);
return (irq_handler_t) IRQ_HANDLED;
}
/* Helper method to print stuff to the terminal */
static void println(char *string)
{
tty = current->signal->tty;
(tty->driver->ops)->write (tty, string, strlen(string));
((tty->driver->ops)->write) (tty, "\015\012", 2);
}
/* Initialize the module and Register the IRQ handler */
static int __init keybrd_int_register(void)
{
myp = kmalloc(sizeof (*myp), GFP_KERNEL);
int result;
/* Request IRQ 1, the keyboard IRQ */
result = request_irq (1, (irq_handler_t) irq_handler, IRQF_SHARED, "keyboard_stats_irq", (void *)(irq_handler));
/* Test simulating keypress */
println ("inserting A ! \n");
ch=65;
tty_insert_flip_char(tty, ch, 0);
con_schedule_flip(tty);
if (result)
printk(KERN_INFO "can't get shared interrupt for keyboard\n");
return result;
}
Everything works as expected, except for when ESC is pressed, then my entire system just freezes and I have to restart my VM.
I've looked through many posts and forums online and can't find an answer.
Any suggestions would be appreciated, thanks in advance.
Got a problem with the Atmel SAMB11 on an explained pro Devboard. I've loaded a quite simple example from Atmel, where a 32KHz Timer is initialized to wake up the µC from sleep and turn on a LED. Problem is, the controller doesn't sleep at all. It just activates the LED immediately and doesn't wait for an interrupt.
#include <asf.h>
// Callback Func to enable LED
static void aon_sleep_timer_callback(void)
{
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
}
//Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Configure Timer with 10sec to overflow
static void configure_aon_sleep_timer(void)
{
struct aon_sleep_timer_config config_aon_sleep_timer;
aon_sleep_timer_get_config_defaults(&config_aon_sleep_timer);
config_aon_sleep_timer.counter = 320000; // Wait about 10sec
aon_sleep_timer_init(&config_aon_sleep_timer);
}
// Configure Callback and enable Interrupt
static void configure_aon_sleep_timer_callback(void)
{
aon_sleep_timer_register_callback(aon_sleep_timer_callback);
NVIC_EnableIRQ(AON_SLEEP_TIMER_IRQn);
}
int main(void)
{
// Setup Clock, LED and Timer
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
configure_gpio_pins();
configure_aon_sleep_timer();
configure_aon_sleep_timer_callback();
// wait for timer to be active
while(!aon_sleep_timer_sleep_timer_active());
// Go to sleep
asm volatile ("wfi");
asm volatile ("nop");
// Enable LED immediately if sleep doesn't work
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
while (true) {}
}
Code seems self-explanatory, but the WFI command doesn't work here. Anyone can help?
Just to add to the answer by Prestige Worldwide.
Make sure AO_GPIO0/1/2 are low (pulldown advised), and no AON Sleep Timer interrupt is occuring, as these will wakeup the SAMB11 from ULP.
Also note that the ULP mode does not seem to work as expected while running a debug session over SWD.
I had all kinds of weirds behaviour when running the debug and sleep/waking up, but no problems at all when running the same code while not debugging. Note this was using Atmel ICE. The Xplored board contains EDBG, and this debugger seems to work ok with ULP.
The resume callback has never fired for me, maybe a bug in the ASF. But I do not need it as I can setup all GPIO/devices after the platform wait.
The WFI call works, it just receives an interrupt almost immediately after it is called, which causes the WFI call to stop blocking and then execution continues to the next line.
You could safely remove everything below // Go to sleep which would allow the main function to return. The AON timer would still execute its callback. However, there are a couple of potential downsides to this approach:
This would not allow the SAMB11 to transition to a lower power mode.
This removes your while-loop at the end of main. In its current state, the while-loop isn't needed, but you might have plans to add code to it later.
Here is an example that configures the AON, configures the SAMB11 to use low power modes, and then loops waiting for platform and/or BLE events. Currently there are no events for the loop to receive. If you want the loop to receive events then you could modify the AON callback to post an event with the at_ble_event_user_defined_post function or modify main() to configure the BLE module before entering the loop.
Use the ASF Wizard to add any of the BLE modules to your project in order to compile this example.
#include <asf.h>
#include "platform.h"
// Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Callback Func to toggle LED
static bool led_is_on = false;
static void aon_sleep_timer_callback(void)
{
configure_gpio_pins();
if(led_is_on) {
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
led_is_on = false;
} else {
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
led_is_on = true;
}
}
// Configure Timer to fire periodically
static void configure_aon_sleep_timer(void)
{
struct aon_sleep_timer_config config_aon_sleep_timer;
aon_sleep_timer_get_config_defaults(&config_aon_sleep_timer);
config_aon_sleep_timer.counter = 32000; // Wait about 1 sec
config_aon_sleep_timer.mode = AON_SLEEP_TIMER_RELOAD_MODE;
aon_sleep_timer_init(&config_aon_sleep_timer);
}
// Configure Callback and enable Interrupt
static void configure_aon_sleep_timer_callback(void)
{
aon_sleep_timer_register_callback(aon_sleep_timer_callback);
NVIC_EnableIRQ(AON_SLEEP_TIMER0_IRQn);
}
int main(void)
{
// Setup Clock
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
plf_drv_status plf_status;
if((plf_status = platform_driver_init()) == STATUS_SUCCESS) {
// Setup LED and Timer
configure_gpio_pins();
configure_aon_sleep_timer();
configure_aon_sleep_timer_callback();
// wait for timer to be active
while(!aon_sleep_timer_sleep_timer_active());
// Go to sleep
release_sleep_lock();
while(true) {
// Replace platform_event_wait with at_ble_event_get if you would like to read the received event.
plf_status = platform_event_wait(0);
}
}
}
Regarding WFI, the following example shows how to turn off most of the interrupts and use WFI to block main(). The LED will toggle every time an interrupt is received. I don't recommend using this as I'm not sure why these interrupts are enabled initially. This is just intended to show how WFI can block on a SAMB11.
#include <asf.h>
#include "platform.h"
// Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Callback Func to toggle LED
static bool led_is_on = false;
static void toggle_led(void)
{
configure_gpio_pins();
if(led_is_on) {
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
led_is_on = false;
} else {
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
led_is_on = true;
}
}
int main(void)
{
// Setup Clock
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
// Clear all interrupts.
NVIC->ICER[0] = 0xFFFFFFFF;
// During testing, interrupts were received about once per second; stopped receiving interrupts (LED stopped flashing) after about 2 minutes.
int loop_count = 0;
while(true) {
__WFI();
toggle_led();
}
}
I am trying to implement a master/slave setup to determine the time of flight between two Arduino Uno boards and ultimately use that as a measure of distance between the two. Using the standard 16MHz crystal and the APC220 from DFRobot communicating between the two is easy but getting a time of flight reading is where I get stuck.
I use the following code on the master side to send the first signal and receive the echo from the slave:
// set pins:
const int switchPin = 3; // pin number of the switch
// variables:
int switchState = 0; // variable for reading switch status
int iDisplay = 1;
unsigned long start, finished, elapsed;
// initialize
void setup()
{
// initialize switch pin as input:
pinMode(switchPin, INPUT);
// initialize serial wireless communication:
Serial.begin(9600);
// read initial state of switch
switchState = digitalRead(switchPin);
}
void displayResult()
{
float h,m,s,ms;
unsigned long over;
elapsed=finished-start;
h=int(elapsed/3600000);
over=elapsed%3600000;
m=int(over/60000);
over=over%60000;
s=int(over/1000);
ms=over%1000;
Serial.print("Raw elapsed time: ");
Serial.println(elapsed);
Serial.print("Elapsed time: ");
Serial.print(h,0);
Serial.print("h ");
Serial.print(m,0);
Serial.print("m ");
Serial.print(s,0);
Serial.print("s ");
Serial.print(ms,0);
Serial.println("ms");
Serial.println();
}
// program loop
void loop()
{
if (Serial.available()>0 && iDisplay == 1)
{
finished=millis();
displayResult();
iDisplay = 0;//Only once
}
// read switch state and print line if state has changed
switch (digitalRead(switchPin)) { // read pin status
case HIGH:
if (switchState == LOW)
{ // check if message has to be sent
start=millis();
delay(200); // for debounce
iDisplay = 1;//Only once
Serial.println(100); // send message about switch
switchState = HIGH; // message has been sent
}
break;
case LOW:
if (switchState == HIGH)
{ // check if message has to be sent
start=millis();
delay(200); // for debounce
iDisplay = 1;//Only once
Serial.println(100); // send message about switch
switchState = LOW; // message has been sent
}
break;
}
}
And the following code for the slave:
// variables:
int intTime = 0;
// initialize
void setup()
{
// initialize serial wireless communication:
Serial.begin(9600);
}
// program loop
void loop()
{
if (Serial.available()>0)
{
intTime = Serial.parseInt();
if (intTime > 1)
{
Serial.println(intTime);
}
intTime = 0;
}
}
Yet this only returns the 200 Milliseconds from the debounce delay, can this be done with the Arduino? Am I getting the math or the code wrong?
I am using Processing language to sketch a rectangle that grows in size with time. Following code is not giving any output.
void setup()
{
size(900,900);
}
void draw()
{
int edge=100;
for(int i=0;i<300;i++)
{
delay(100);
edge++;
rect(100,100,edge,edge);
}
}
I suspect having wrongly used delay() function.
Here is one such "roll your own" delay method which is good for most purposes. Just change the values passed into the delay method to alter the timing. This just outputs "start" and "end" roughly every 2 seconds for example.
void draw()
{
System.out.println("start");
delay(2000);
System.out.println("end");
delay(2000);
}
void delay(int delay)
{
int time = millis();
while(millis() - time <= delay);
}
I recommend rolling your own delay system using the millis() function.
Have a look at this example.
With processing, the screen does not get refreshed until the program flow reaches the end of draw()
Try the following:
void setup()
{
size(900,900);
frameRate(10);
}
int edge = 100;
void draw()
{
edge++;
rect(100,100,edge,edge);
}