0

I am sending a String 1 and a String 0 encoded with ASCII from Python to a C program on my Arduino UNO over a serial port.

I am able to receive the encoded data in C which is 0x31 for 1 and 0x30 for 2, this is what I expected as it is ASCII hex for char 1 and char 2.

I can read/use this in its ASCII state. But now I want this data: 0x31 to be turned into an int 1 or char 1 and 0x30 into an int 0 or char 0 in C. I have tried atoi(receivedData) (Which is literally: ASCII to int) but this doesn't work, I have sent the atoi(receivedData) result back and I get a 0x00 in Python.

How can I go about doing this?

Here is my C code:

uint8_t receivedData;

void uart_init()
{
    // set the baud rate
    UBRR0H = 0;
    UBRR0L = UBBRVAL;
    // disable U2X mode
    UCSR0A = 0;
    // enable receiver & transmitter
    UCSR0B = (1<<RXEN0) | (1<<TXEN0); // Turn on the transmission and reception circuitry
    // set frame format : asynchronous, 8 data bits, 1 stop bit, no parity
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
}

void receive(void)
{
    loop_until_bit_is_set(UCSR0A, RXC0);
    receivedData = UDR0;
}

void transmit(uint8_t dataa)
{
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = dataa
}

void processData() {
    cleanUDR0();

    // 0x31 is ascii code for 1, 0x30 is 0
    // led turns on if input == 1 (0x31) and turns off if led == 0 (0x30)
    receive();

    transmit(receivedData);

    int temporary = atoi(receivedData);

    if (temoraray == 1){
        PORTD = 0xff; // Turning LEDs on
    }
    else if (temporary == 0){
        PORTD = 0x00; // Turning LEDs off
    }
}

void cleanUDR0(void) {
    unsigned char y;
    while (UCSR0A & (1<<RXC0)) y=UDR0;
}

int main(void)
{
   DDRD = 0xFF;
   uart_init();

   While(1) {
      processData();
   }
}

Here is my Python code:

import time
import threading
import serial


class SerialT(threading.Thread):
    connected = False

    serialC = serial.Serial("COM4", 19200)

    while not connected:
        serin = serialC.read()
        connected = True

    while True:
        myStr1 = '1'
        myStr0 = "0"

        serialC.write(myStr1.encode('ascii'))
        print(int(chr(ord(serialC.read()))))

        time.sleep(2)

        serialC.write(myStr0.encode('ascii'))
        print(int(chr(ord(serialC.read()))))

        time.sleep(2)
Hoxlegion
  • 277
  • 1
  • 3
  • 14
  • Are you sure `atoi()` will take hex strings as input? – Micrified Nov 07 '19 at 15:43
  • 1
    Assuming you're using Python 3, you can skip the encoding and just create your strings as `bytes` objects, then send those: `myStr1 = b'1', myStr0 = b'0'`. Additionally, `serial.Serial.read` returns `bytes` objects, so you can just call `decode` on the result, then `int` on that. Or, just call `int` on the bytes object directly, so long as it represents a base-10 number: `int(b'1') -> 1` – b_c Nov 07 '19 at 15:51
  • 1
    In regards to the c-half, it looks like you're storing as a `uint8_t`. To parse it into its represented int, casting to `char` and then following [this answer](https://stackoverflow.com/a/41365557/4739755) should work. – b_c Nov 07 '19 at 16:09
  • 1
    @b_c Thank you, this made my code cleaner and it works now! Been stuck for a while haha – Hoxlegion Nov 07 '19 at 16:18

1 Answers1

1

Check comments for the answer.

C

receivedDataTemp = receivedData - '0';

Python

myStr1 = b'1'
myStr0 = b'0'

serialC.write(myStr1)
print(int(serialC.read().decode()))
Wang Liang
  • 4,244
  • 6
  • 22
  • 45
Hoxlegion
  • 277
  • 1
  • 3
  • 14