Perte d'octets

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

Depuis quelques jours j’affronte quelques problèmes de communication série entre un Atmega328 et mon PC si bien que j'ai décidé de faire le test qui me semble le plus simple pour vérifier cela : un simple programme "loopback" sur l'Atmega.

J'ai donc d'un côté un Atmega328 qui tourne avec le code affiché ci-après, et de l'autre côté l'adaptateur USB<->série présent sur ma vielle carte "Arudino UNO" (non peuplé par son propre Atmega), un Atmega8U2. De plus j'utilise pour ces tests un très petit bitrate (1200bit/s) afin d'écarter les problèmes d'imprécisions de l'horloge interne.

Le code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define F_CPU 8000000

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

#define USART_BAUDRATE 1200
#define BAUD_PRESCALE (((( F_CPU / 16) + ( USART_BAUDRATE / 2) ) / ( USART_BAUDRATE ) ) - 1)

typedef uint8_t   u8;
typedef uint16_t  u16;

int main(void)
{
        UCSR0B = (1<<RXEN0)|(1<<TXEN0);
        UCSR0C = (1<<USBS0)|(3<<UCSZ00);

        UBRR0H = (unsigned char)(BAUD_PRESCALE>>8);
        UBRR0L = (unsigned char)BAUD_PRESCALE;

        UCSR0B |= (1 << RXCIE0);

        sei();

        while(1) {}
}

ISR(USART_RX_vect, ISR_BLOCK)
{
        u8 received_byte;
        received_byte = UDR0;
        UDR0 = received_byte;
}

Du côté du python j'utilise la bibiothèque "serial". Lorsque je teste l'envoi de bits individuels je ne perd rien :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
ser = serial.Serial("/dev/ttyACM0", 1200, timeout=1)

ok = 0
ko = 0
for i in range(nb_bytes):
    char = random.randint(0,255)
    ser.write([char])
    result = ser.read()
    if len(result) > 0 and result[0] == char:
        ok += 1
    else:
        ko += 1

print("nb_chars = {}".format(nb_bytes))
print("ok = {}".format(ok))
print("ko = {}".format(ko))
1
2
3
4
>>> test3.test_indiv(100)
nb_chars = 100
ok = 100
ko = 0

En revanche quand j'envoie directement "un paquet" de plusieurs octets, certains n'arrivent pas (ou ne reviennent pas en tout cas) de manière semble-t-il aléatoire:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
>>> ser = serial.Serial('/dev/ttyACM0', 1200, timeout=1)                                                                
>>> data = [random.randint(0,255) for _ in range(100)]
>>> ser.write(data)
100
>>> data2 = list(ser.read(100))
>>> data
[178, 193, 217, 98, 243, 147, 153, 73, 191, 191, 5, 190, 141, 94, 133, 121, 25, 255, 56, 7, 139, 77, 211, 56, 216, 182, 159, 201, 156, 235, 96, 144, 30, 73, 216, 196, 97, 201, 183, 204, 212, 145, 182, 59, 186, 191, 191, 35, 161, 252, 103, 1, 177, 204, 28, 205, 245, 51, 59, 83, 136, 105, 224, 255, 35, 116, 98, 199, 79, 240, 52, 224, 78, 92, 178, 122, 75, 184, 5, 75, 250, 128, 83, 190, 197, 14, 235, 147, 58, 20, 80, 248, 34, 224, 146, 225, 158, 72, 70, 118]
>>> data2
[178, 193, 217, 98, 243, 147, 153, 73, 191, 191, 5, 190, 94, 133, 121, 25, 255, 56, 7, 139, 77, 211, 216, 182, 159, 201, 156, 235, 96, 144, 30, 73, 196, 97, 201, 183, 204, 212, 145, 182, 59, 186, 191, 35, 161, 252, 103, 1, 177, 204, 28, 205, 245, 59, 83, 136, 105, 224, 255, 35, 116, 98, 199, 240, 52, 224, 78, 92, 178, 122, 75, 184, 5, 250, 128, 83, 190, 197, 14, 235, 147, 58, 20, 80, 34, 224, 146, 225, 158, 72, 70, 118]
>>> data == data2
False

On pourrait supposer que le problème provienne d'un dépassement de buffer quelque part (sur l'adaptateur USB<->série ?), sauf que dans ce cas comment expliquer le placement random des manques (dans cet exemple le premier octet manquant est le 13ème) ?

L’imprécision de l'horloge parait être une éventualité mais… à ce faible bitrate ?
Est-ce que la lib python envoie "trop vite" pleins d'octets et le micro n'a "pas le temps" de suivre ? Ça parait curieux.

En tout cas quand les octets sont envoyés individuellement c'est vraiment lent.

Voilà, si quelqu'un a une piste je suis preneur :)
Merci d'avance
Emmflo

EDIT: En fait je suis un débile, j'avais pas le bon format de frame série.

1
>>> ser = serial.Serial('/dev/ttyACM2', 9600, timeout=1, bytesize=8, stopbits=2)

Et pouf tout va mieux. Donc oui pour ceux qui ne le savaient pas (comme moi :> Même si en fait c'est logique…) ça peut marcher à moitié si on met pas le bon format :>

Édité par Emmflo

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte