Why doesn't the LED turn off? - timer

I have a program (copied below) that has an alarm that starts in 10 seconds, which starts a LED that blinks every two seconds. I would like to push a button that turns off the alarm / LED. The LED blinks as intended but does not turn off when I push the button. Any idea why? Code below:
#include <Time.h>
#include <TimeAlarms.h>
#define buttonPin 2 // assigns pin 2 as buttonPin
#define ledPin 13 // assigns pin 13 as ledPin
int buttonState; // variable for reading the pushbutton status
int lastButtonState = LOW;
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
Serial.begin(9600); // start Serial Monitor
setTime(0, 0, 0, 1, 1, 2018); // set time to 00:00:00 Jan 1 2018
Alarm.alarmRepeat(0, 0, 10, DailyAlarm); // Alarm triggered in 10 sec
pinMode(ledPin, OUTPUT); // assigns ledPin as led output pin.
pinMode(buttonPin, INPUT); // assigns buttonPin as input pin
// digitalWrite(ledPin, ledState); // LED is off initially
}
void loop() {
digitalClockDisplay();
Alarm.delay(1000); // wait one second between clock display
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = HIGH;
Serial.print(buttonState);
}
}
}
void DailyAlarm() {
Serial.println("Alarm");
while (buttonState == LOW) {
blink(2000); // blink every 2s
}
}
void blink(int period) {
digitalWrite(ledPin, HIGH);
delay(period / 2);
digitalWrite(ledPin, LOW);
delay(period / 2);
}
void digitalClockDisplay() {
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println();
}
void printDigits(int digits) {
Serial.print(":");
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}

int buttonState; // variable for reading the pushbutton status
You haven't initialized the button state
Try
boolean buttonState = LOW
And Don't mix integers and booleans
use this
boolean lastButtonState = LOW;
instead of
int lastButtonState = LOW;

Related

Unable to produce 1s delay using timer module

I am trying to generate a 1 second delay, using a timer module.
The value in the timer register is 61 DEC, which will generate an interrupt every ~50ms, which will increment the value of a variable named value.
After 20 interrupts ~1 sec will have passed, which will alter the state of an LED. But this doesn't seem to work as intended. The oscillator frequency is 4MHz, the prescaler value of the timer module is 256 and the targeted microcontroller is PIC16F72.
Here is the code:
char value;
bit state;
void Interrupt(){
if(TMR0IF_bit){
value++;
TMR0 = 61;
TMR0IF_bit = 0;
}
}
void main(){
value = 0;
state = 0;
TRISB.RB0 = 0;
OPTION_REG = 0x87;
TMR0 = 61;
INTCON = 0xA0;
while(1){
if(value == 20){
value=0;
state=~state;
PORTB.RB0=state;
}
}
}
The declaration of the ISR is wrong
Switch:
void Interrupt(){
to:
void interrupt(){
And don't forget the volatile
volatile char value;

Stepper Motor won't stop rotating

I'm trying to get my 28BYJ-48 Stepper Motor to rotate one quarter of a revolution and then stop, but I'm having trouble implementing that in code. What I find is no matter how small I make the numbers in my code or even alter it in ways that make me think it'd work properly, I can't get it to stop rotating. Below is the helpful part of the code.
#define STEPPER (*((volatile uint32_t *)0x4000703C))
// Move 1.8 degrees clockwise, delay is the time to wait after each step
void Stepper_CW(uint32_t delay) {
Pt = Pt->Next[clockwise]; // circular
STEPPER = Pt->Out; // step motor
if(Pos==199) { // shaft angle
Pos = 0; // reset
}
else {
Pos--; // CW
}
SysTick_Wait(delay);
}
// Move 1.8 degrees counterclockwise, delay is wait after each step
void Stepper_CCW(uint32_t delay) {
Pt = Pt->Next[counterclockwise]; // circular
STEPPER = Pt->Out; // step motor
if(Pos==0) { // shaft angle
Pos = 199; // reset
}
else {
Pos++; // CCW
}
SysTick_Wait(delay); // blind-cycle wait
}
// Initialize Stepper interface
void Stepper_Init(void) {
SYSCTL_RCGCGPIO_R |= 0x08; // 1) activate port D
SysTick_Init();
Pos = 0;
Pt = &fsm[0];
// 2) no need to unlock PD3-0
GPIO_PORTD_AMSEL_R &= ~0x0F; // 3) disable analog functionality on PD3-0
GPIO_PORTD_PCTL_R &= ~0x0000FFFF; // 4) GPIO configure PD3-0 as GPIO
GPIO_PORTD_DIR_R |= 0x0F; // 5) make PD3-0 out
GPIO_PORTD_AFSEL_R &= ~0x0F; // 6) disable alt funct on PD3-0
GPIO_PORTD_DR8R_R |= 0x0F; // enable 8 mA drive
GPIO_PORTD_DEN_R |= 0x0F; // 7) enable digital I/O on PD3-0
}
// Turn stepper motor to desired position
// (0 <= desired <= 199)
// time is the number of bus cycles to wait after each step
void Stepper_Seek(uint8_t desired, uint32_t time) {
short CWsteps;
if((CWsteps = (desired-Pos))<0) {
CWsteps+=200;
}
// CW steps is > 100
if(CWsteps > 100) {
while(desired != Pos) {
Stepper_CCW(time);
}
}
else {
while(desired != Pos) {
Stepper_CW(time);
}
}
}
Stepper_Seek gets called here...
#include <stdint.h>
#include "stepper.h"
#define T1ms 16000 // assumes using 16 MHz PIOSC (default setting for clock source)
int main(void) {
Stepper_Init();
Stepper_CW(T1ms); // Pos=1; GPIO_PORTD_DATA_R=9
Stepper_CW(T1ms); // Pos=2; GPIO_PORTD_DATA_R=5
Stepper_CW(T1ms); // Pos=3; GPIO_PORTD_DATA_R=6
Stepper_CW(T1ms); // Pos=4; GPIO_PORTD_DATA_R=10
Stepper_CW(T1ms); // Pos=5; GPIO_PORTD_DATA_R=9
Stepper_CW(T1ms); // Pos=6; GPIO_PORTD_DATA_R=5
Stepper_CW(T1ms); // Pos=7; GPIO_PORTD_DATA_R=6
Stepper_CW(T1ms); // Pos=8; GPIO_PORTD_DATA_R=10
Stepper_CW(T1ms); // Pos=9; GPIO_PORTD_DATA_R=9
Stepper_CCW(T1ms); // Pos=8; GPIO_PORTD_DATA_R=10
Stepper_CCW(T1ms); // Pos=7; GPIO_PORTD_DATA_R=6
Stepper_CCW(T1ms); // Pos=6; GPIO_PORTD_DATA_R=5
Stepper_CCW(T1ms); // Pos=5; GPIO_PORTD_DATA_R=9
Stepper_CCW(T1ms); // Pos=4; GPIO_PORTD_DATA_R=10
Stepper_Seek(8,T1ms);// Pos=8; GPIO_PORTD_DATA_R=10
Stepper_Seek(0,T1ms);// Pos=0; GPIO_PORTD_DATA_R=10
while(1) {
Stepper_CW(10*T1ms); // output every 10ms
}
}
I thought it could have been that it kept resetting its position and starting again after it reset but even after commenting out the line it wouldn't fix.
Thank you everyone in advance!
Your wrap-around logic is backward in both Stepper_CW() and Stepper_CCW(). Take the former as the example. Suppose you're trying to reach 198, and Pos is initially 1:
On the first call, Pos is decremented to 0. This is unequal to 198, so the function is called again.
On the second call, Pos is decremented to 199. This is unequal to 198, so the function is called again.
On the third call, the wrap-around case is triggered, and Pos is set to 0. This is unequal to 198 ....
The state after step (3) is the same as the state after step (1) -- infinite loop.

Seven-segment display using 595

I am having some trouble coding my seven-segment display using a shift register and push button. The aim is for the display to count up when the button is pressed. 0-9 then; A, B, C, D, E, and F. I did manage to get this working at first but the task was changed so the "shiftOut" command was not allowed to be used.
With my adjusted code my seven-segment display doesn't seem to be working at all now. I have tried to do a lot of my own troubleshooting (i.e. looking into debouncing, arrays, and bit-banging). Any help would be appreciated. Thanks. PS: this is my first question so sorry if the format is wrong.
/* Pins to connect to common-cathode LED display via a 74HC595:
DP-7, A-6, B-5, C-4, D-3, E-2, F-1, G-15
*/
const byte ledCharSet[128] = {
// 00-0F: Hex digits
B10000001, B11001111, B10010010, B10000110, // 0123
B11001100, B10100100, B10100000, B10001111, // 4567
B10000000, B10000100, // 89
B10001000, B11100000, B10110001, B11000010, // AbCd
B10110000, B10111000, // EF
};
//// Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//// Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;
//// Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;
//// Pin connected to display's common annode
const int faderPin = 10;
int _B = 7;
bool b;
int count=0;
int value;
long time = 0;
long debounce = 500;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(_B, INPUT_PULLUP);
b = true;
toggleLatch();
toggleCLK();
Serial.begin(9600);
}
void toggleLatch() {
digitalWrite(latchPin, HIGH); digitalWrite(latchPin, OUTPUT);
}
void toggleCLK() {
digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW);
}
void loop() {
unsigned char count; // debounce counter
if (b != digitalRead(_B)) {
for(count = 0; count<20 && b != digitalRead(_B); count++);
//register the change if we have confirmed it 20 consecutive times
b=((count>=20 && b!=digitalRead(_B))?!b:b);
if(!b) {
count--;
} // button is pushed
}
toggleLatch();
void shiftBit(bool dataPin) { digitalWrite(ledCharSet,dataPin); toggleCLK(); }
void shiftByteMSF(unsigned char b) {
unsigned char b = ledCharSet[count];
unsigned char m; // use m to select the bits in b one at a time
m = 1;
for (m = B10000000; m>0; m <<= 1) {
if (b & m) {
digitalWrite(dataPin, HIGH);
} else {
digitalWrite(dataPin, LOW);
}
}
toggleLatch();
}
if (count==16) {
count=0; //reset
}
}
This is the first code I used, which worked fine.
/* Pins to connect to common-cathode LED display via a 74HC595:
DP-7, A-6, B-5, C-4, D-3, E-2, F-1, G-15 (shiftOut using MSBFIRST)
*/
const byte ledCharSet[128] = {
// 00-0F: Hex digits
B10000001, B11001111, B10010010, B10000110, // 0123
B11001100, B10100100, B10100000, B10001111, // 4567
B10000000, B10000100, // 89
B10001000, B11100000, B10110001, B11000010, // AbCd
B10110000, B10111000, // EF
};
//// Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//// Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;
//// Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;
//// Pin connected to display's common annode
const int faderPin = 10;
int _B = 7;
int reading;
int previous = LOW;
int counter=0;
long time = 0;
long debounce = 500;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(_B, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
reading = digitalRead(_B);
Serial.print(counter);
if (reading == HIGH && previous == LOW && millis() - time > debounce) {
counter++;
time = millis();
}
previous = reading;
byte bitsToSend = ledCharSet[counter];
bitsToSend = bitsToSend ^ B11111111;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend);
digitalWrite(latchPin, HIGH);
digitalWrite(11, 255);
digitalWrite(11, 0);
if (counter==16) {
counter=0; //reset count
}
}

PING sensor on RPI, start counting when less than 40cm?

I have a PING sensor (HC-SR04) hooked up to my RPI. I want it to start counting when the sensor sees less than 40 cm. It should stop counting again when the sensor again sees less than 40 cm, print out the time and start counting again.
How can I do this?
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#define TRUE 1
#define TRIG 5
#define ECHO 6
void setup() {
wiringPiSetup();
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
//TRIG pin must start LOW
digitalWrite(TRIG, LOW);
delay(30);
}
int getCM() {
//Send trig pulse
digitalWrite(TRIG, HIGH);
delayMicroseconds(20);
digitalWrite(TRIG, LOW);
//Wait for echo start
while(digitalRead(ECHO) == LOW);
//Wait for echo end
long startTime = micros();
while(digitalRead(ECHO) == HIGH);
long travelTime = micros() - startTime;
//Get distance in cm
int distance = travelTime / 58;
return distance;
}
int i;
int main(void) {
setup();
while (1)
{
printf("Distance: %dcm\n", getCM());
delay(250);
}
return 0;
}
The code doesn't measure the distance. It only measures the duration of the reflected signal. To get the distance you need to measure the delay between the beginning of ping, and the beginning of echo:
startTime = micros();
digitalWrite(TRIG, HIGH);
delayMicroseconds(20);
digitalWrite(TRIG, LOW);
//Wait for echo start
while(digitalRead(ECHO) == LOW);
long travelTime = micros() - startTime;
Of course, this is just a skeleton: you need to debounce the echo to guard yourself against background noises and other glitches.

Input capture value is double in atmea128

I am learning embedded C with Atmega128 and Atmel Studio.
I want to write code that shows the temperature and humidity from a sensor.
I am learning Input Capture and my first question is:
I get IC with value 5000(period) but I think 2500 is correct. Am I calculating it right? If so, do you have any idea why IC has the wrong value?
16000.000/64 = 250000
1 second 250000 puls
100 ms x = 2500
Board info:
avr128
16.000.000 external clock.
philips puls generator info:
Repitation 100 mili s
Duration 10 ms
5 volt
My code
volatile uint32_t iccnt=0,ovfcnt=0;
volatile uint32_t myCapt [2],lastCapt;
//__________________________
void initTimer()
{
TCNT1 =0;//Max=65535
TCCR1B |= 1<<CS10 | 1<<CS11 ;
// 1<<CS10 | 1<<CS11 ;//16000000/16=250000
//250000/65535=3.81
//TCCR1B |= 1<<WGM13 |1<<WGM12;
TIMSK |= 1<<TOIE1;
TIFR = 1<<TOV1;
sei();
}
void initInputCapture()
{
// First Capture on rising edge
TCCR1B |=1<<ICES1;
//ic intrrupt flag enable
TIMSK |= 1<< TICIE1;
// set input pin to get signal
}
void initlcd()
{
lcd_init(LCD_DISP_ON_CURSOR_BLINK);
lcd_clrscr();
}
void ShowA(unsigned int a)
{
char aa[11];
if (a >32000) {
itoa(a - 32000,aa,10);
lcd_puts("32000+");
lcd_puts(aa);
} else {
itoa(a,aa,10);
lcd_puts(aa);
}
}
ISR(TIMER1_OVF_vect)
{
ovfcnt++;
}
ISR(TIMER1_CAPT_vect)
{
iccnt++;
myCapt[iccnt % 2] = ICR1 - lastCapt;
lastCapt = ICR1;
}
void ShowCaptureTime2()
{
lcd_clrscr();
ShowA (iccnt);
lcd_puts(": \n");
ShowA(myCapt[(iccnt - 1) % 2]);
for (int j=0;j<(1000) ;j++)
{
for (int i=0;i<4000;i++)
{
}
}
}
//*******************************
//*******************************
int main(void)
{
DDRG = 0b11111111;
int cnt = 0;
initlcd();
initTimer();
initInputCapture();
while(1)
{
ShowCaptureTime2();
}
}
I could find the answer yesterday. code has no problem. Pulse generator work not correktly! incorrect input!!!! – samsoft

Resources