3

I wrote a program in python that receive a binary number from Atmega32 (a microcontroller) via USART and prints it in output.

in the other hand, My Atmega32 read its PINA on the interrupt firing and sends its value to the computer using USART.

this is my python program :

>>> import serial
>>> ser=serial.Serial ('COM3')
>>> ser.open()
>>> while(1):
    ser.read()

when I connect PINA pins in a way that make00000111 (equal to 7), I see the below output in python:

'7'
'7'
'7'
'7'
'7'
'7'
.
.
.

But when I connect PINA pins in a way that make 10000111 (equal to 135), I see the below output in python :

'1'
'3'
'5'
'1'
'3'
'5'
'1'
'3'
'5'
'1'
'3'
'5'
'1'
'3'
'5'
'1'
'3'
'5'
.
.
.

As you see above, it prints 135 in three line! Why?


FYI : This is the program that I wrote for Atmega32 in CodeVision :

interrupt [EXT_INT0] void ext_int0_isr(void)
{
printf("%d",PINA);
}

Update : I change the programs in ATMEGA-side and Python-Side as suggested in the answers:

My AVR interrupt routine :

interrupt [EXT_INT0] void ext_int0_isr(void)
{
printf("%d",PINA);
printf("%d\n",0);
}

And this is my output in python :

>>> while(1):
    ser.readline()


'35\n'
'135\n'
'135\n'
'135\n'
'135\n'
'135\n'
'135\n'
'agi\x16agi\x16\xff135255\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'1350\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'1350\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'1350\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'
'135255\n'
'1350\n'
'135255\n'

As you see, the output is not that we expected from the AVR code and Python code!

TheGoodUser
  • 1,188
  • 4
  • 26
  • 52
  • probably its about that _read()_ function. Do you know what methods include that func? Like _print ("Hello",sep="-",end="")_ – GLHF Dec 27 '14 at 08:55
  • @qqvc As far as I know, this function only receive a number as size! I replace the default (=1) with other numbers, but nothing change. – TheGoodUser Dec 27 '14 at 09:05

2 Answers2

4

ser.read() is only going to return 1 byte at a time. Specify a count to read multiple bytes.

>>> x = ser.read()          # reads one byte
>>> x = ser.read(10)        # reads up to ten bytes 

You can also try ser.readline() instead.

Edit:

Can you try inserting a newline character in the program you wrote for Atmega32:

interrupt [EXT_INT0] void ext_int0_isr(void)
{
printf("%d\n",PINA);
}

and then look for newline charcter before printing:

mylist=[]
while True:
    char = ser.read()
    if char == '\n':
        print(mylist)
        mylist = []
        continue
    mylist.append(char)

or use ser.readline() as suggested by @hyades in the comments.

Ujjwal
  • 3,088
  • 4
  • 28
  • 36
  • As far as I know, both **7** (=`0b00000111`) and **135** (=`0b10000111`) are one byte! So why should I change the default value in `read()` function? It receive `135` as one byte, but prints it in three line (probably as three byte!) why? – TheGoodUser Dec 27 '14 at 09:07
  • @TheGoodUser-Amir what are you printing? the value of `s.read()` ?? – hyades Dec 27 '14 at 09:15
  • @TheGoodUser-Amir can you change it to `printf("%d\n",PINA);` and then show the output with `readline()` – hyades Dec 27 '14 at 09:25
  • @hyades I tried your comment, but nothing changed. just a single empty line appears after `5`s – TheGoodUser Dec 27 '14 at 09:39
  • @TheGoodUser-Amir were you trying with `read()` or `readline()` ? – hyades Dec 27 '14 at 09:44
  • @TheGoodUser-Amir Then you know wrong. If you output these data as ASCII (with `printf("%d\n", PINA)`), you get one byte for each character. If you want to really send them as binary values, you have to send them in a different way: with `putc(PINA)` or with `printf("%c", PINA)`. – glglgl Dec 27 '14 at 09:45
  • @ujjwal Dear friend , I understand your code. It can help me to make the output like the output I except. But it doesn't solve the problem. Promlem is "Why?" NOT "How I can see the output in the form it must be". I mean, I want to know why it prints **135** in three line. – TheGoodUser Dec 27 '14 at 09:45
  • @hyades You was right. I wrongly tried `readline(1)` instead of `readline()`. With the `ser.readline()` I can see the output in a correct form. But as I said in the previous comment, I want to know the origin of the problem. Thank you :) – TheGoodUser Dec 27 '14 at 09:49
  • 1
    @TheGoodUser-Amir: Your device returns does not return a single *number* (byte) of `135`, but the 3-character *string* `"135"` (which encoded as 3 separate bytes in ASCII). Hence, if you read only one character at a time, you will only get `"1"`, `"3"`, and `"5"` *separately*. – Rufflewind Dec 27 '14 at 09:53
2

I'll try to explain what happens:

On the µC side, you transfer a value over a serial line. You have to decide in which format this happens and to make the receiver use the same format.

You have decided to use ASCII. So the device converts each value into its digits and sends them over the line. Fist problem here is that you don't have a separator. If you have 5 times the value 77, it sends 7777777777. But how do you know that it is not 10 times the value 7? Thus, you have to add a line separator.

Other options could be to send the data binary (just as they are) or as hex data with all 2 bytes long (with printf("%02x", PINA)). Then you don't need a separator.

Which way you choose, you'll have to make the receiver compatible with the sender.

  • If you keep it as it is (but with a \n), you can work with .readline().
  • If you send it as binary, you can keep the receiver as you have it.
  • If you want to use the hex format, you alwas have to read 2 bytes and convert them as you want.
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • @hyades No. `PINA` is already a kind of int (indeed, an unsigned char). `%d` turns it into its ASCII representation. – glglgl Dec 27 '14 at 09:58