0
\$\begingroup\$

I've been programming my atmega 328p to automate my coffe machine. The timer is set using the bluetooth module HC-06, or by a set of configuration buttons that I'm gonna develop yet (the full code is on my github: https://github.com/andrehrema/Cafeteira).

I've faced some problems with serial communication, so right now I'm trying to establish a communication between the microcontroller and my pc.

To send data I'm using putty and python with serial package, both with baudrate equal to 9600.

The data is stored in the queue buffer_rx_bth, and each queue's node is of type BT_node (BT = bluetooth).

The character '|' symbolyzes the end of the string and It allows the ATmega response.

Below is the piece of code used in UART communication:

#include<avr/io.h> 
#include<avr/interrupt.h>


typedef struct node_BT BT_node;
typedef struct queue_BT_data BT_data;

struct node_BT{
        char byte;
        BT_node *next;
};


struct queue_BT_data{
        BT_node *hd;
        int index;
        BT_node *tl;
};

volatile BT_data * add_inst(volatile BT_data *buffer_bth, char command){

        BT_node *inst = malloc(sizeof(BT_node));
        inst->byte = command;

        if (buffer_bth->hd == 0){
                buffer_bth->hd = inst;
                buffer_bth->hd->next = 0;                 
                buffer_bth->tl = buffer_bth->hd;
                return buffer_bth;
        }
        else{
                inst->next = buffer_bth->tl->next;
                buffer_bth->tl->next = inst;
                buffer_bth->tl = inst;
        }

        return buffer_bth;
}


volatile BT_data * remove_inst(volatile BT_data *buffer_bth){ 
        while(buffer_bth->hd->byte != '|'){

                BT_node *delete = buffer_bth->hd;

                buffer_bth->hd=buffer_bth->hd->next;
                free(delete);
        }

        BT_node *delete = buffer_bth->hd;
        if(buffer_bth->hd == buffer_bth->tl)
                buffer_bth->tl = buffer_bth->tl->next;

        buffer_bth->hd=buffer_bth->hd->next;
        free(delete);
        return buffer_bth;
}



volatile BT_data *buffer_rx_bth;

ISR(USART_RX_vect){ //interruption handler
        UCSR0B &= ~(1<<TXCIE0); // transmition interruption disabled

        char result = UDR0;         
        buffer_rx_bth = add_inst(buffer_rx_bth, result);

        UCSR0B |= (1<<TXCIE0); // transmition interruption enabled
}

int main (void){

    buffer_rx_bth = malloc(sizeof(BT_data)); 
    buffer_rx_bth->hd=0; // queue head
    buffer_rx_bth->tl=0; // tail head


    BT_node * pointer = 0;

    while(1){
        sei() 
        set_sleep_mode(SLEEP_MODE_IDLE);
        sleep_mode();


        if (buffer_rx_bth->tl->byte == '|'){ //verify if it is the final character

                        if (pointer == 0){
                                PORTB ^= 4;
                                pointer = buffer_rx_bth->hd;
                        }


                        if ( (UCSR0A & (1<<UDRE0)) && pointer!=0){
                                UDR0 = pointer->byte;

                                if(pointer->byte == '|'){

                                        remove_inst(buffer_rx_bth);                                         
                                        ponteiro = 0;
                                }
                                else
                                        pointer = pointer->next;
                        }  
    }

}



When data is sent byte per byte, as shown below, the microcontroller send an equal response, as I expected.

import serial

    uc = serial.Serial("/dev/ttyACM0",9600)
    uc.write('A')
    uc.write('B')
    uc.write('C')
    uc.write('|') 
    uc.stop()

response: ABC|

However, when more than one byte is sent, with the method write, the answer is completely random.

import serial

    uc = serial.Serial("/dev/ttyACM0",9600)
    uc.write("ABC|")

response: random string

Why is this happening? How can I solve it?

\$\endgroup\$
6
  • \$\begingroup\$ Your code doesn't compile. What does pointer = pointer->prox; do? \$\endgroup\$ Jan 29, 2020 at 19:56
  • \$\begingroup\$ Bruce, the entire code can be accessed on my github. If you wanna try run it: github.com/andrehrema/Cafeteira But, the code is commented in portuguese. I will do some modifications and, until tomorrow afternoon, It will be in english. \$\endgroup\$ Jan 29, 2020 at 22:55
  • \$\begingroup\$ I get it now:- 'prox' is short for 'next' in Portuguese. \$\endgroup\$ Jan 30, 2020 at 2:11
  • \$\begingroup\$ I updated the question and the the full code on my github. Now you can compile it. If you find any problem, please, let me know it. \$\endgroup\$ Jan 30, 2020 at 13:39
  • 1
    \$\begingroup\$ Arduino is not a PC. Variables shared with an ISR must be treated with care, see this and using malloc on an old 8 bitter is madness, see this. Lots of other minor errors as well, I'd recommend studying the basics of MCU programming. This tutorial seems decent. \$\endgroup\$
    – Lundin
    Jan 31, 2020 at 8:46

1 Answer 1

5
\$\begingroup\$

Most likely the malloc and free are not thread safe so you can't allocate in interrupt and free in main loop. In general, there should be no dynamic memory allocation in interrupts. At least you should disable receive interrupts when popping a byte from the linked list. And in general rarely there should be need for linked lists using dynamic allocation in AVR applications either. Just use a preallocated array as a ring buffer, it will be more efficient and can work from main and interrupt contexts. Also, there is no TX complete interrupt function anywhere in the code, yet the code disables and enables it in RX interrupt - it is possible it jumps to reset vector after transmitting each byte, so it works for single bytes every now and then.

\$\endgroup\$
1
  • \$\begingroup\$ thank you for your support. I've tried a couple of times using a fixed buffer length. But the problem persists. The full code is available on my github [github.com/andrehrema/Cafeteira ], if you prefer, you can try to compile and execute it. \$\endgroup\$ Jan 30, 2020 at 13:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.