UART RX Interrurpt fired too early - avr

I'm doing a small project, where I want to transmit a text via a cable to my Atmega328p.
I first created the project on an Arduino Uno (with pure C), where the transmission works.
Now I switched to a standalone 328p and tried it there.
But now the Problem is, that my RX-Complete Interrupt is fired too early. In fact it is even fired, when nothing has been transmitted. It will fired when I just touched the cable (the isolated parts) .
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/setbaud.h>
void setup(void){
CLKPR = 0;
//Set Output
DDRC |= (1 << PC0) | (1 << PC1) |(1 << PC2) |(1 << PC3) |(1 << PC4) | (1 << PC5);
DDRD |= (1 << PD6) | (1 << PD7);
// Interrupts
sei();
// Init UART
// Set baud
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
// Enable UART Receive and Receivecomplete Interrupt
UCSR0B = (1<<RXEN0) | (1 << RXCIE0);
// Set frameformat to 8 Data and 1 Stopbit
UCSR0C = ((1<<UCSZ00)|(1<<UCSZ01));
}
int main(void){
setup();
while(1){
}
return 0;
}
ISR(USART_RX_vect){
// Enable some LEDs
}
Edit: Picture of my Setup:
I use the Arduiono just for Powering my Breadboard. 5V and GND are connected.
The AVR MKII ISP is Connected via some Pins to flash the µC. The two cables are used for UART RX.
The Pushbutton is just for RESET
Edit 2: I just tried to power it via an external source and a raspberrypi. There is the same effect everywhere

Of course. RXC flag is set when there are unread data in the receive buffer.
This flag is used to generate the RX interrupt.
Since you never read UDR inside your interrupt, this flag remains set, and, therefore just after interrupt routine is completed, it is starts again. And again. And again....

The Rx line should not be floating. Its a high impedance input and should be driven to a specific level. Your cables act like an antenna and if you touch the cable it gets worse because there is capacitive coupling between the cable and your body. This may result in high frequency noise on your input which may trigger the Rx interrupt.
Further make sure that the 328p local power supply is properly decoupled. I don't see any capacitors near the controller on your breadboard. Check GND connection between Arduino and 328p (mandatory).

Without looking at your setup it's hard to tell what's going wrong, but if you're touching an isolated cable and getting a response from the processor, then I would check common grounds between the devices if you're powering the ATMega via a battery, make sure the battery ground is touching the device that's receiving and transmitting, as any potential difference in power levels could cause the little magnetic field that you give off to be amplified into something that the core registers as a high bit.If possible, post a picture of your setup!
Also when programming with ATMel chips, burning the arduino bootloader and going the simple(r) C code way never hurt.

Related

Acquiring data from LeddarVu8 Lidar using Arduino

I'm working on a room visualization project, similar to this (taken from this video):
Im using LeddarVu8 from leddartech (see image below), arduino uno (with rs485shield):
I've also used the code provided from leddartech of simple16channel (no lcd):
#include "C:\Program Files (x86)\Arduino\libraries\Leddar.h"
/*
Simple Leddar(TM) Example - Without LCD
Language: Arduino
This program lists the detections read on the serial port of the Arduino.
Can be used with Arduino IDE's Serial Monitor.
Shields used:
* RS-485 Shield
Created 01 Jun. 2015
by Pier-Olivier Hamel
This example code is in the public domain.
*/
Leddar16 Leddar1(115200,1);
//Baudrate = 115200
//Modbus slave ID = 01
void setup()
{
//Initialize Leddar
Leddar1.init();
}
void loop()
{
char result = Leddar1.getDetections();
if (result >= 0)
{
for (int i = 0; i < Leddar1.NbDet; i++)
{
Serial.print("Segment: ");
Serial.print(Leddar1.Detections[i].Segment);
Serial.print(" Distance: ");
Serial.print(Leddar1.Detections[i].Distance);
Serial.print("\n");
}
}
else
{
Serial.print("Error: ");
Serial.print((int)result);
Serial.print("\n");
}
delay(50);
}
(from https://support.leddartech.com/downloads/files/89-leddarsdk3-2-0-pi2-tar-gz)
The problem is that serial monitor of the arduino only outputs a series of ?????. Why is that?
The problem is that serial monitor of the arduino only outputs a series of ?????. Why is that?
Because you have connected the TX of the LIDAR to the TX of the Arduino. The Serial Monitor window "listens" to the Arduino TX pin (via USB), so the Serial Monitor is actually listening to the LIDAR. The LIDAR serial is running at 115200, but your Serial Monitor is probably set to 9600. When the baud rates don't match, you'll get garbage characters.
Also notice that you have two serial TX pins connected to each other. This will also corrupt the characters if the Arduino and the LIDAR both try to transmit at the same time.
You may be able to connect the LIDAR RX to the Arduino TX, and the LIDAR TX to the Arduino RX. This would allow you to see the Leddar library commands on the Serial Monitor window. It would also cause all Serial prints to go to the LIDAR (and the PC). This might be ok if the Leddar command packets have a special format. This would allow the Leddar to ignore your debug prints, because they would not formatted correctly.
In that configuration, you would have to disconnect Arduino pin 0 to upload new sketches over USB. Some people put a switch in that wire to make it easy to disconnect.

change PWM duty cycle from within ISR

I have little problems implementing a dither function to upgrade the PWM resolution of my ATmega88 and the leds it's controlling.
My thought was, to use a "kind of" floating number, consisting of two uint8_t as "decimal places" so that e.g. "255.31" would be represented by "0xff.0x1f" (BYTE_HIGH.BYTE_LOW).
Now I want the value in the OCR to dither between BYTE_HIGH and BYTE_HIGH+1 and for this I need a second counter (besides the timer itself) to generate an overlayed dutycycle (the duty cycle of the timer has to be incremented after (int) 255-BYTE_LOW cycles). But managing this stuff in the main() results in flicker and so I'd like to do this in an ISR called on timer overflow.
My avr is running at 20 MHz and to get a sufficient dither frequency I cannot use a prescaler higher than 8. Do you think, I might be calling the ISR too frequently? But there is not too much code in the ISR, though.
Another problem I could think of is, that the ISR has to write the OCR which might be read by the timer at the same time, but isn't this kind of "thread save" as the timer does never write to OCR?
I have not found anything concerning my problem appropriately and so I hope to get some hints. See my code below
#include <avr/interrupt.h>
#include <avr/io.h>
#define compare_register OCR2B //duty cycle
volatile uint8_t dither_count=0;
volatile uint8_t BYTE_HIGH=0;
volatile uint8_t BYTE_LOW=0;
void init_pwm(void){
//some standard pwm initializations
TCCR2A |= (1 << COM2A1);
TCCR2A |= (1 << COM2B1);
// non inverting, fast PWM mode and prescaler to
TCCR2A |= (0 << WGM21) | (1 << WGM20);
TCCR2B |= (1 << CS21);
// set desired pin as an output (not sure, if it's the correct pin, because I left out other pins in use)
DDRD = (1 << DDD3)|(1<<DDD4);
// enable interrupt on timer overflow
TIMSK2 |= (1<<TOIE2);
// enable global interrupts
sei();
}
ISR(TIMER2_OVF_vect){
dither_count++;
if(dither_count<=BYTE_LOW){
compare_register=BYTE_HIGH+1;
}else{
compare_register=BYTE_HIGH;
}
}
int main(){
init_pwm();
//this or any function dimming the leds
BYTE_HIGH=10;
BYTE_LOW=1;
}
This theoretically should work, but unfortunately it doesn't work in real. The ISR gets called, but does not act as desired. Do I call the variables correctly inside of the ISR?
I would be glad if someone would see a fundamental misstake I did, especially because I do not have any serial interface working for debugging...
Edit: meanwhile I found out, that obiously the ISR gets stuck and will block any code executed in my main function...
I tried your program on an Arduino Uno. This board is based on a
ATmega328P which, save for some extra memory, is basically the same as
your Mega88 (same datasheet). I first added the following lines at the
end of main():
init_pwm();
// Blink the LED on PB5.
DDRB |= _BV(PB5);
for (;;) {
PINB |= _BV(PB5);
_delay_ms(400);
}
The first line is obviously needed for the PWM to work. The LED blinking
is just a test to see whether the program gets stuck in the ISR or not.
The result is: it does not. The LED blinks just as expected. The PWM
output looks also OK on the scope. Notice that, contrary to what the
comment in the code says, you are configuring the timer in phase
correct PWM mode, not in fast PWM. The timer period is then 2×255 timer
clock cycles instead of 256.
I disassembled the binary and tried to count the number of CPU cycles
needed to service the interrupt. With the program compiled at the -Os
optimization level, I got about 50. Given that the interrupt fires every
2×255×8 = 4080 cycles, that's about 1.2% of the CPU power
spent servicing the interrupt.

Arduino Uno + ESP8266 12E + Blynk + Relay

I started adventure with arduino and programming 2 months ago.So, I am new in this topics.
Until now I realized few projects including Blynk connected with arduino. The last one was similar to one described in topic but I used the ENC28j60 instead of ESP8266 module and then it worked fine.
The problem started with ESP module.
Short description of project:
The main idea is to control AC light with Blynk App support.
First of all I made a connection according to picture below:
As power source I used the USB phone charger connected with step by voltage converter to get in final the 3.3V source.
I additionally connected the Arduino Uno with relay module like this:
Arduino ====> Relay module
5V ====> VCC
GND ====> GND
Pin 5 ====> IN1
Everythink you can see in pictures below (sorry for quality)
And for now I did almost every step (with so many problems). Here I mean:
1. I checked if arduino is connected with ESP module by serial port -> system report "ready" status.
2. I upload the below (template) Arduino IDE sketch for my project:
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "***";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "***";
char pass[] = "***";
void setup()
{
// Debug console--
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
}
void loop()
{
Blynk.run();
}
And finally I started the New project in Blynk. I set the Arduino uno as a hardware model and WiFi as connection type. Then I added the Button and set the Output to D5.
And now (close to the end of project) I met with a problem. After pushing the connect button (in up-right corner) I receive the information that device is connected (Online). Then when I try to push the button to Active Relay - nothing happens.
Whats more. I tried with different pins on Arduino with the same results. And I don't know why (probably because I have still small knowladge) but when I set the Button output value to D2 - after connection when I push it then the diode on ESP module Turn OFF and Turn ON.
I tried to find solution on this forum and in many other places for last 3 days but without any results. That's why I decided to ask You for help. Do you know what did I wrong or what should I add to project to make connection between the Blynk and relay work correct?
Write if you will need some more or detailed information from my side.
Why are you using both the uno and the esp? You can just use the esp instead of the combo, will make your project less power hungry and smaller. If you wonder about using just the esp, you can use the nodemcu boards (which can be found for less that 4€ per unit in China).
I've some example sketches for this (with temperature and humidity), if you want to take a look at those.
When looking at the pictures and code you have postet, it seems that you have flashed the ESP with a Arduino sketch. This is fine if you would like to activate the relay directly with the ESP (without the Arduino UNO).
Then you just have to connect the relay to the ESP instead of to the Arduino. Unfortunately not all relay boards can operate with the 3.3V logic that the ESP supplies, but maybe you'r lucky.
On the other hand, if you would like to use the Arduino UNO with the ESP as Wi-Fi, then you would have to reflash the ESP with the original AT firmware. Then you could connect it to the Arduino and use a sketch that looks something like this.
#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
char auth[] = "YourAuthToken";
char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(2, 3);
// pin 3 connected to ESP RX and pin 2 connected to ESP TX
// Your ESP8266 baud rate:
#define ESP8266_BAUD 115200
ESP8266 wifi(&EspSerial);
void setup()
{
// Debug console
Serial.begin(9600);
delay(10);
// Set ESP8266 baud rate
EspSerial.begin(ESP8266_BAUD);
delay(10);
Blynk.begin(auth, wifi, ssid, pass);
}
void loop()
{
Blynk.run();
}
And you should remove the connection between RST and GND on the Arduino

Detect USB Connection Event on STM32

I'm currently working with a USB-enabled low power device that I'm having a bit of trouble with. During normal operation, the system clock is set to a significantly slower speed (since this is a data logger only active once every few minutes, this isn't a problem). However, when the device is then plugged into a USB port on a computer, it needs to recognize this, initialize the USB stack (which I can do), and reset the system clock to full speed (I can do this, as well).
My problem, as you might have noticed, is the "USB Connected" event. I'm looking through the STM32 evaluation materials and they have in the IRQn table a "USB_FS_WKUP_IRQn", and the STM32 eval board also has USB-5V power routed to pin PE6, which can also act as WKUP3.
Do I need to enable an external interrupt for that pin, or is there a better way to detect such an event and set/reset the clocks as needed?
Thanks in advance.
Basing on the interrupt name you mentioned I found this implementation:
// Enable the USB Wake-up interrupt
NVICInit.NVIC_IRQChannel = USB_FS_WKUP_IRQn;
NVICInit.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_Init(&NVICInit);
It seems you don't need much more. The implementation can differ from the STM32 family you use.
I use the stm32l4
I set up an interrupt on the Vbus pin.
While not in USB mode, configure the pin as a pull-down (so it isn't floating).
Your pin and interrupt line would be different, but
//Configure the pin
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA9 */
GPIO_InitStruct.Pin = VBUS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(VBUS_GPIO_Port, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
//Configure the interrupt
EXTI_ConfigTypeDef exti_conf;
exti_conf.Line = EXTI_LINE_9;
exti_conf.GPIOSel = EXTI_GPIOA;
exti_conf.Mode = EXTI_MODE_INTERRUPT;
exti_conf.Trigger = EXTI_TRIGGER_RISING;
HAL_EXTI_SetConfigLine(&hexti_vbus, &exti_conf);
And make sure you have an interrupt handler taken care of. Set a flag for going to USB in the interrupt handler. And you should be set.

Turn an LED on or off in AT Mega-1284P Xplained

I am a beginner in AT Mega-1284P Xplained.
I want to turn an LED on and then off (say, LED0) after some specified time in AT Mega 1284P Xplained board from ATMEL. To my surprise, I found no official documentation for this rudimentary task but several different function calls - all of which failed compilation - searching on the web.
Please mention the API call as well as the header file that needs to be included for this. I am using AVR Studio 6.
I will assume a led is connected to pin 0 at port b on the AtMega1284P. The following program should make the led blink.
#include <util/delay.h>
#include <avr/io.h>
int main() {
// Set the pin 0 at port B as output
DDRB |= (1<<PB0);
while(1) {
// Turn led on by setting corresponding bit high in the PORTB register.
PORTB |= (1<<PB0);
_delay_ms(500);
// Turn led off by setting corresponding bit low in the PORTB register.
PORTB &= ~(1<<PB0);
_delay_ms(500);
}
}
Answering my own question: I found Atmel had an example code that covered a bunch of sensors and other peripheral components including LEDs for Mega-1284P. The links are link and link. Besides, very hard to find locations (they did not show up on web searches), the websites are _very_slow. Atmel, are you listening?

Resources