Wake up Adafruit Feather 32u4 from sleep mode with external interrupt - c

I have an Adafruit Feather ATMega 32u4. I want to put it into sleep mode and wake it up with pressing a switch as an external interrupt. This is what I tried so far and which worked:
switching a LED on and off with the switch
putting the Adafruit to sleep and let it wake up with a watchdog timer.
I tried to combine the code examples that I found in the Internet to make the code fit my board. I manage to put it to sleep but then I have to reset it because the Interrupt doesn't work. I would be very happy for any help and please don't blame me, I am a complete beginner!
Here is my code:
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>
int pin2 = 2;
void pin2Interrupt(void) {
/* This will bring us back from sleep. */
detachInterrupt(digitalPinToInterrupt(2));
}
void enterSleep(void) {
/* Setup pin2 as an interrupt and attach handler. */
delay(100);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(digitalPinToInterrupt(2), pin2Interrupt, RISING);
if (digitalRead(pin2)){
sleep_mode();
}
/* The program will continue from here
* First thing to do is disable sleep.
*/
sleep_disable();
}
void setup() {
Serial.begin(9600);
/* Setup the pin direction. */
pinMode(pin2, INPUT_PULLUP);
Serial.println("Initialisation complete.");
}
int seconds = 0;
void loop() {
delay(1000);
seconds++;
Serial.print("Awake for ");
Serial.print(seconds, DEC);
Serial.println(" second");
if(seconds == 3){
Serial.println("Entering sleep");
delay(200);
seconds = 0;
enterSleep();
}
}
Update:
#include "LowPower.h"
#include "avr/interrupt.h"
#define BUTTON 3
#define LEDPIN 13
void wakeUp() {
detachInterrupt(digitalPinToInterrupt(BUTTON));
}
void Blink(byte ledPin, int msDelay, byte loops) {
for (byte i=0; i<loops; i++) {
digitalWrite(ledPin, LOW);
delay(msDelay);
digitalWrite(ledPin, LOW);
delay(msDelay);
}
}
void setup() {
pinMode(BUTTON, INPUT);
digitalWrite(BUTTON, LOW);
pinMode(LEDPIN, OUTPUT);
digitalWrite(LEDPIN, LOW);
}
void loop() {
cli();
EIMSK &= ~(1 << INT0);
EICRA |= (1 << ISC01) | (1 << ISC00);
EIMSK |= (1 << INT0);
attachInterrupt(digitalPinToInterrupt(BUTTON), wakeUp, CHANGE);
sei();
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
Blink(LEDPIN, 100, 3);
Serial.println("AWAKE!");
delay(100);
}

Related

sim808 freezes after one SMS using stm32

I am trying to design a GPS car tracker with a SIM808 module using a STM32F103RET6 header board and I want to get the location link messaged to my phone by sending an SMS to the module. Right now my code works but only when I reset the board after sending each SMS. I attached my code can you figure out what is the problem?
main code :
#include <stm32f10x.h>
#include "usart.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
char S=0x1A;
#define Enter usart_sendchar('\n');
#define CR usart_sendchar('\r');
#define GIM usart_sendchar('"');
#define SUB usart_sendchar(S);
#include "stm32f10x.h"
#include <string.h>
char get_Enter = 0;
uint8_t ch;
char str1[300];
char str2[100];
int i=0;
char flag=0;
char str_tmp[20];
char str_tmp2[20];
char* p;
volatile uint32_t msTicks;
//calling all the functions
void Send_SMS(char *text);
void CMTI(void);
void wait_to_get(char ch);
void del_All_SMS(void);
void CMGF_1(void);
void Delay (uint32_t Time);
void CMGR (void);
void CGNSPWR_1(void);
void CGNSINF(void);
void interrupt_activation(void);
void CGNSINF_C(void);
void AT(void);
void Delay (uint32_t dlyTicks);
void SysTick_Handler(void);
// the interrupt handler for the systick module
void SysTick_Handler(void) {
msTicks++;
}
void Delay (uint32_t dlyTicks) {
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks)< dlyTicks);
}
void Send_SMS(char *text)
{
CMGF_1();
Delay(500);
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGS=");
Delay(500);
usart_sendstring(str_tmp);
GIM
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"+98905xxxxxxx");
Delay(500);
usart_sendstring(str_tmp);
GIM
Enter
CR
Delay(500);
usart_sendstring(text);
Enter
CR
str_tmp[0]='\0';
Delay(500);
SUB
Delay(100);
del_All_SMS();
}
void USART1_IRQHandler(void) {
ch = USART1->DR & 0xFF;
if (ch == '\n'){ // 13 enter
get_Enter =1;
}
else{
str1[i]= ch;
i++;
}
}
void CMGF_1(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGF=1");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void del_All_SMS(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGD=1,4");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void CMGR(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGR=1");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void CGNSINF(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CGNSINF");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void CGNSPWR_1(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CGNSPWR=1");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void AT(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
int main()
{
SystemInit();
SysTick_Config(SystemCoreClock/1000); // setup systick timer for 1ms interrupts
usart_init();
AT();
p=NULL;
check:AT();
Delay(2000);
p=strstr(str1,"OK");
if(p==NULL) goto check;
CMGF_1();
Delay(500);
CGNSPWR_1();
Delay(500);
del_All_SMS();
Delay(500);
RCC->APB2ENR |= (1<<3);
GPIOB->CRL &= ~0xF;
GPIOB->CRL |= 0x3;
while (1)
{
if (get_Enter ==1)
{
if (flag==0){
////waiting for +CMTI: from sim800
do
{
p=strstr(str1,"+CMTI:");
}
while(p==NULL);
Delay(1000);
// sending AT+CMGR=1 command
if (p!=NULL)
{
CMGR();
Delay(350);
flag=1;
}
}
if (flag==1) {
p=strstr(str1,"+CMGR");
if (p){
p=strstr(str1,"loc");
if (p!=NULL)
{
CGNSINF();
Delay(300);
}
else if (p==NULL)
{
del_All_SMS();
memset(str1, 0, 300);
flag=0;
}
p=strstr(str1,"+CGNSINF:");
if (p)
{
float a[5];
char str2[80];
const char s[2] = ",";
char *token;
// getting the lattitude and longitude
token = strtok(p, s);
for (int i=0;i<5;i++){
sprintf( str2," %s\n", token );
a[i]=atof(str2);
token = strtok(NULL, s);
}
sprintf(str2,"https://maps.google.com/?q=%.6f,%.6f",a[3],a[4]);
Send_SMS(str2);
p=NULL;
del_All_SMS();
flag=0;
memset(str1, 0, 300);
}
}
}
}
}
}
usart code :
#include "stm32f10x.h"
#include "usart.h"
char str[200];
char data;
//// initialize usart
void usart_init(void)
{
RCC->APB2ENR |= ( 1UL << 0); /* enable clock Alternate Function */
AFIO->MAPR &= ~( 1UL << 2); /* clear USART1 remap */
RCC->APB2ENR |= ( 1UL << 2); /* enable GPIOA clock */
GPIOA->CRH &= ~(0xFFUL << 4); /* clear PA9, PA10 */
GPIOA->CRH |= (0x0BUL << 4); /* USART1 Tx (PA9) output push-pull */
GPIOA->CRH |= (0x04UL << 8); /* USART1 Rx (PA10) input floating */
RCC->APB2ENR |= ( 1UL << 14); /* enable USART#1 clock */
USART1->BRR=0x1D4C; // 9600 #72MHz
// USART1->BRR = 0x0271; /* 115200 baud # PCLK2 72MHz */
USART1->CR1 = (( 1UL << 2) | /* enable RX */
( 1UL << 3) | /* enable TX */
( 0UL << 12) ); /* 1 start bit, 8 data bits */
USART1->CR2 = 0x0000; /* 1 stop bit */
USART1->CR3 = 0x0000; /* no flow control */
USART1->CR1 |= ( 1 << 13); /* enable USART */
USART1->CR1 |= ( 1UL << 5); // RXNE interrupt enable
NVIC_SetPriority(USART1_IRQn,5); /* Default priority group 0, can be 0(highest) - 31(lowest) */
NVIC_EnableIRQ(USART1_IRQn); /* Enable UART0 Interrupt */
}
void usart_sendchar(char data){
while(!(USART1->SR&(1<<7)));
USART1->DR=data;
}
char usart_getchar(void)
{
while (!(USART1->SR&(1<<5)));
data=USART1->DR ;
return data;
}
void usart_getstring(char *str)
{
char *temp = str;
do{
*temp = usart_getchar();
usart_sendchar (*temp) ;
} while(*(temp++) != 0x0D );
*(temp-1) = 0;
}
void usart_sendstring(char *s)
{
while (*s)
{
usart_sendchar(*s);
s++;
}
}

init External Interrupt on LPC213x/4x

Hi I write code below for initial External Interrupt for LPC2138 in KEIL 4.7 Compiler and when run code in proteus software , code dosent Work. I double check VIC and EXTINT registers seems correct. thanks
Project Picture on Proteus
one Switch on EXTINT2 (P0.15) and one LED on P1.25
#include <LPC213x.h>
void delay(int count);
void init_ext_interrupt(void);
__irq void Ext_ISR(void);
int main (void)
{
init_ext_interrupt(); // initialize the external interrupt
while (1)
{
}
}
void init_ext_interrupt(void) //Initialize Interrupt
{
EXTMODE = (1<<2); //Edge sensitive mode on EINT2
EXTPOLAR &= ~(1<<2); //Falling Edge Sensitive
PINSEL0 = 0x80000000; //Select Pin function P0.15 as EINT2
/* initialize the interrupt vector */
VICIntSelect &= ~(1<<16); // EINT2 selected as IRQ 16
VICVectAddr5 = (unsigned)Ext_ISR; // address of the ISR
VICVectCntl5 = (1<<5) | 16;
VICIntEnable = (1<<16); // EINT2 interrupt enabled
EXTINT &= ~(1<<2); //Set interrupt
}
__irq void Ext_ISR(void) // Interrupt Service Routine-ISR
{
IO1DIR |= (1<<25);
IO1SET |= (1<<25); // Turn ON LED
delay(100000);
IO1CLR |= (1<<25); // Turn OFF LED
EXTINT |= (1<<2); //clear interrupt
VICVectAddr = 0; // End of interrupt execution
}
void delay(int count)
{
int j=0,i=0;
for(j=0;j<count;j++)
{
for(i=0;i<35;i++);
}
}
You should correct the line:
(VICVectCntl5 = (1<<5) | 16;)
to:
(VICVectCntl5 = 0x20 | 16;)
as datasheet said.

MSP430 Function Call Being Skipped

I am programming an MSP430 microcontroller with the MSP430 LaunchPad Dev Kit and I am running into some problems on this simple code.
#include <msp430.h>
void Delay(void);
#define LED1 BIT0 //define LED1 as bit 0 (0x00)
#define LED2 BIT6 //define LED2 as bit 6 (0x40)
#define delayTime 20000 //define iTime as 20000
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; //stop watchdog timer
P1DIR |= (LED1|LED2); //set P1.0 and P1.6 to output direction (P1.3 is naturally an input)
P1OUT |= LED1; //set P1.0 high so the LEDs will blink alternatively
while(1)
{
Delay();
P1OUT ^= (LED1|LED2); //toggle P1.0 using exclusive-OR
}
}
void Delay(void)
{
int i = 0;
while(delayTime > i)
{
i++;
}
}
This code compiles fine, but when debugging the code, the function call 'Delay()' is skipped entirely and the function is never entered. However, when I give the function a return type of 'unsigned int' like this:
unsigned int Delay(void)
{
int i = 0;
while(delayTime > i)
{
i++;
}
return 1;
}
I can call the Delay function in an if statement like the one below and the debugger will enter the function.
if(Delay() == 1)
{
P1OUT ^= (LED1|LED2); //toggle P1.0 using exclusive-OR
}
I'm sure there is some simple oversight that I'm making. I can't for the life of me figure out why the debugger is skipping my first void function call. Any wisdom?
swineone has responded with the following correct solution in a comment:
"Try changing the declaration int i = 0; to volatile int i = 0; in the
Delay() function. This tells the optimizer not to touch that variable,
and may be the difference between the optimizer optimizing the code
away or not."
Thanks for the help!
It's recommended to work with interrupts. Such a task goes to this:
#include "io430.h"
#define ON 1
#define OFF 0
#define LED1 P1OUT_bit.P0
#define LED2 P1OUT_bit.P6
void init(void)
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
P1OUT = 0x00;
P1DIR = 0xFF;
// initialize Timer0_A
TA0CCR0 = 62500; // set up terminal count
TA0CTL = TASSEL_2 + ID_3 + MC_1; // configure and start timer
// enable interrupts
TA0CCTL0_bit.CCIE = 1; // enable timer interrupts
__enable_interrupt(); // set GIE in SR
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void myTimerISR(void)
{
LED1 = ~LED1;
}

PWM fadeing LED on arduino

I`m trying to blink led with PWM on Arduino, and I dont know whats wrong. But my LED is not fadeing. What is wrong? I think that I have bad registers settings, but Im not sure. Led is connected on arduino pin 11. Thank you.
#include <avr/io.h>
#include <util/delay.h>
const int delay=1000;
void initialize_PWM()
{
TCCR0A|=(1<<WGM00)|(1<<WGM01)|(1<<COM0A1);
TCCR0B=1;
DDRB|=(1<<PB3);
}
void set_pwm(uint8_t data)
{
OCR0A=data;
}
int main (void)
{
initialize_PWM();
uint8_t brightness=200;
while(1)
{
for(brightness=0;brightness<255;brightness++)
{
set_pwm(brightness);
_delay_ms(1);
}
for(brightness=255;brightness>0;brightness--)
{
set_pwm(brightness);
_delay_ms(1);
}
}
return 0;
}
Have you looked at the 'Fade' example program?
/*
Fade
This example shows how to fade an LED on pin 9
using the analogWrite() function.
This example code is in the public domain.
*/
int led = 9; // the pin that the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
// the setup routine runs once when you press reset:
void setup() {
// declare pin 9 to be an output:
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
// set the brightness of pin 9:
analogWrite(led, brightness);
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
// reverse the direction of the fading at the ends of the fade:
if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount ;
}
// wait for 30 milliseconds to see the dimming effect
delay(30);
}
See http://arduino.cc/en/Tutorial/Fade
Your code seems correct, but you are using timer0, that can generate pwm on Arduino UNO's pin 5 and 6, as shown in the datasheet. So you should set the ddrd bit 6 with a
DDRD |= (1 << PD6)
, that is pin 6 on Arduino, not pin 11. If you want pwm on pin 11 you should use timer2 instead.

Counting pulses using a swiss flow meter with an Arduino, how is it done?

So I'm trying to count the pulses of a swiss flow SF800 flow sensor / meter in my current Arduino project, but I'm currently not getting any data printed out to the console. My Arduino sketch looks like the following,
// global variables should be identified with _
// flow_A LED
int led = 4;
// relay_A
const int RELAY_A = A0;
// variables from sketch example
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
// FLOWMETER SHIT
// flowmeter 0 pulse (input) = digital pin 2
// https://github.com/Kegbot/kegboard/blob/master/arduino/kegboard/kegboard_config.h
// which pin to use for reading the sensor? kegboard-mini shield has digital pin 2 allocated
# define FLOWSENSORPIN 2
int rpmcount = 0;
int rpm = 0;
unsigned long lastmillis = 0;
void setup() {
// initialize serial
Serial.begin(9600); // open serial port, sets data rate to 115200bps
inputString.reserve(200);
pinMode(RELAY_A, OUTPUT);
// flowmeter shit
pinMode(FLOWSENSORPIN, INPUT);
digitalWrite(FLOWSENSORPIN, HIGH); // Need to set these HIGH so they won't just tick away
attachInterrupt(0, rpm_fan, FALLING); // interrupt is attached, is on pin two(2).
}
void open_valve() {
digitalWrite(RELAY_A, HIGH); // turn RELAY_A on
// Serial.println("Valve Open");
Serial.write("{valve_open}");
}
void close_valve() {
digitalWrite(RELAY_A, LOW); // turn RELAY_A off
// Serial.println("Vavle Closed");
Serial.write("{valve_close}");
}
void flow_A_blink() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for one second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
void flow_A_blink_stop() {
digitalWrite(led, LOW);
}
// flowmeter shit
void getFlow() {
Serial.println("reached getFlow function");
if(millis() - lastmillis == 1000) { // Update every one second, this will be equal to reading frequency (Hz).
detachInterrupt(0); // Disable interrupt when calculating
rpm = rpmcount * 60; // Convert frequency to RPM, note: this works for one interruption per full rotation.
Serial.print("RPM =\t"); // print the word "RPM and tabl.
Serial.print(rpm); // print the rpm value
Serial.print("\t Hz=\t"); // print the word "Hz".
Serial.println(rpmcount); // print revolutions per second or Hz. And print new line or enter.
rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Update lastmillis
attachInterrupt(0, rpm_fan, FALLING); // enable interrupt
}
}
void rpm_fan() { // this code will be executed every time the interrupt 0 (pin2) gets low.
rpmcount++;
}
/*
* Main program loop, runs over and over repeatedly
*/
void loop() {
if(stringComplete) {
// Serial.println(inputString);
if(inputString.equals("{open_valve}\n")) {
// Serial.println("opening valve.");
open_valve();
getFlow();
}
if(inputString.equals("{close_valve}\n")) {
// Serial.println("close vavle.");
close_valve();
}
// clear the string:
inputString = "";
stringComplete = false;
}
}
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
*/
void serialEvent() {
while(Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
// Serial.println(inputString.length());
}
}
The following code changes seem to be printing the RPM and Hz values now.
// flow_A LED
int led = 4;
// relay_A
const int RELAY_A = A0;
// variables from sketch example
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
// FLOWMETER SHIT
// flowmeter 0 pulse (input) = digital pin 2
// https://github.com/Kegbot/kegboard/blob/master/arduino/kegboard/kegboard_config.h
// which pin to use for reading the sensor? kegboard-mini shield has digital pin 2 allocated
# define FLOWSENSORPIN 2
int rpmcount = 0;
int rpm = 0;
unsigned long lastmillis = 0;
void setup() {
// initialize serial
Serial.begin(9600); // open serial port, sets data rate to 115200bps
inputString.reserve(200);
pinMode(RELAY_A, OUTPUT);
// flowmeter shit
pinMode(FLOWSENSORPIN, INPUT);
digitalWrite(FLOWSENSORPIN, HIGH); // Need to set these HIGH so they won't just tick away
attachInterrupt(0, rpm_fan, FALLING); // interrupt is attached, is on pin two(2).
}
void open_valve() {
digitalWrite(RELAY_A, HIGH); // turn RELAY_A on
// Serial.println("Valve Open");
Serial.write("{valve_open}");
}
void close_valve() {
digitalWrite(RELAY_A, LOW); // turn RELAY_A off
// Serial.println("Vavle Closed");
Serial.write("{valve_close}");
}
void flow_A_blink() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for one second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
void flow_A_blink_stop() {
digitalWrite(led, LOW);
}
// flowmeter shit
void getFlow() {
// Serial.println("reached getFlow function");
if(millis() - lastmillis >= 1000) { // Update every one second, this will be equal to reading frequency (Hz). Using >= should be safter
// Serial.println("reached inside if statement");
detachInterrupt(0); // Disable interrupt when calculating
rpm = rpmcount * 60; // Convert frequency to RPM, note: this works for one interruption per full rotation.
Serial.print("RPM =\t"); // print the word "RPM and tabl.
Serial.print(rpm); // print the rpm value
Serial.print("\t Hz=\t"); // print the word "Hz".
Serial.println(rpmcount); // print revolutions per second or Hz. And print new line or enter.
rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Update lastmillis
attachInterrupt(0, rpm_fan, FALLING); // enable interrupt
}
}
void rpm_fan() { // this code will be executed every time the interrupt 0 (pin2) gets low.
rpmcount++;
}
/*
* Main program loop, runs over and over repeatedly
*/
void loop() {
if(stringComplete) {
// Serial.println(inputString);
if(inputString.equals("{open_valve}\n")) {
// Serial.println("opening valve.");
open_valve();
}
if(inputString.equals("{close_valve}\n")) {
// Serial.println("close vavle.");
close_valve();
}
// clear the string:
inputString = "";
stringComplete = false;
}
getFlow();
}
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
*/
void serialEvent() {
while(Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
// Serial.println(inputString.length());
}
}

Resources