Hi everyone. I have a problem with data transmission from Arduino Mega2560 Rev3 via USART to my computer. I want to send input capture value (ICR4) with every edge change to rising.I used USB-USART converter FTDI with RT232RL and normal printer cable to check difference. With both of cables i get the same output. For test i send const "test" variable. In first 2min i get correct output but then i get incorrect data. What i mean by that, sometimes i lose byte and my program in Python read incorrect value. Please help me to seciure this transmission. My meansure signal is generate from Arduino Uno TimerOne lib. I use VS code with Platform IO plugin. Here is code:
#include <avr/interrupt.h> #include <avr/io.h> #include <util/delay.h> #include <stddef.h> #include <stdint.h> #include <string.h> #define F_CPU 16000000 #define _NOP() \ do { \ __asm__ __volatile__("nop"); \ } while (0) static constexpr uint32_t UART_BAUD_RATE{1000000}; const uint16_t test =6411; volatile uint16_t startseq = 2; volatile uint16_t endseq = 3; void UARTSetup(uint32_t baudrate) { // UART settings: // * 8 data bits // * No parity bits (default) // * 1 stop bit (default) // * Asynchronous Normal mode (default) uint32_t const baseClockFrequency = F_CPU; uint32_t const uartClockDivider = 16; uint16_t const UBRRValue = static_cast<uint16_t>( (baseClockFrequency / (uartClockDivider * baudrate)) - 1); // Setup TX0 pin as output (PE1) DDRE |= _BV(PE1); // Set baudrate UBRR0 = UBRRValue; // Enable transmitter UCSR0B |= _BV(TXEN0); // Set 8-bit frame format UCSR0C |= (1<<UMSEL01)|_BV(UCSZ01) | _BV(UCSZ00); } void UARTSendByte(uint8_t value) { // Wait until the previous transmission has ended while (!(UCSR0A & _BV(UDRE0))) ; // Put the data into buffer UDR0 = value; } void UARTSendBytes(uint8_t const* data, size_t length) { for (uint8_t const* ptr = data; ptr != (data + length); ptr++) { UARTSendByte(*ptr); } } void UARTSendString(char const* string) { UARTSendBytes(reinterpret_cast<uint8_t const*>(string), strlen(string)); } template <typename T> void UARTSendValue(T value) { UARTSendBytes((uint8_t const*)&value, sizeof(value)); } /// Timer-related functions /// void ICTimerInit() { // Use Timer4, because only ICP4 and ICP5 are accessible on Arduino Mega // (which is bullshit) // Set capture on rising edge, and prescaler to 1 (timer should be clocked at // F_CLK) TCCR4B |= _BV(ICES4) | _BV(CS40); // Enable input capture and overflow interrupts TIMSK4 |= _BV(ICIE4) | _BV(TOIE4); } void resetSystemTimerPrescaler() { // Make sure that there's no prescaler on Fclk // To change prescaler, set CLKPCE bit in CLKPR register to 1, // while simultanously setting the prescaler bits - here, we // set them to 0 because we don't want any prescaler CLKPR = _BV(CLKPCE); // Wait 4 cycles to make sure the change is applied before proceeding _NOP(); _NOP(); _NOP(); _NOP(); } // Input-capture event ISR(TIMER4_CAPT_vect) { // Send the value over UART UARTSendValue(static_cast<uint16_t>(test)); } // Overflow event ISR(TIMER4_OVF_vect) { // Add the max value of ICR register // to indicate that overflow happened // timeBetweenCaptures += 0xFFFF; } int main() { cli(); // disable interrupts resetSystemTimerPrescaler(); LEDSetup(); UARTSetup(UART_BAUD_RATE); ICTimerInit(); // enableClockTestOutput(); sei(); // enable interrupts while (true) ; }