@dekees, ik moet even zoeken.
@henri62, dat ga proberen als ik weer in de schuur ben, simpel is beter.
de code waarmee de data word verstuurt.
draait in een atmega32, (en als ik mij niet vergis heeft dekees hier nog aan mee geholpen).
//*** 24-7-2021 *******************************************************************************************
// TESTING THE RS485 UART TSOP ***************************************************************************
// fuse: ext. crystal/resonater medium freq. start up 16 64
// fuse: J-tag uitvinken
#define F_CPU 8000000UL // 8 MHz clock speed
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
int receivedbyte = 0;
int bytetosend = 0;
int column_counter_byte_1 = 0;
int column_counter_byte_2 = 0;
int column_counter_byte_3 = 0;
int byte_1 = 0;
int byte_2 = 0;
int byte_3 = 0;
uint8_t BitCounter = 0;
volatile start_scan = 0;
int start_send_data_byte_1 = 0;
int start_send_data_byte_2 = 0;
int start_send_data_byte_3 = 0;
int shift_byte_out = 0;
uint8_t columns_byte_1 [300];
uint8_t columns_byte_2 [300];
uint8_t columns_byte_3 [300];
ISR(TIMER1_COMPA_vect)
{
static uint8_t BitCounter = 0;
switch(BitCounter++)
{
case 0 : { byte_1 |= (PINC & 0x80); PORTD |= (1 << PIND3); break; }
case 1 : { byte_1 |= (PINC & 0x40); break; }
case 2 : { byte_1 |= (PINC & 0x20); break; }
case 3 : { byte_1 |= (PINC & 0x10); break; }
case 4 : { byte_1 |= (PINC & 0x08); break; }
case 5 : { byte_1 |= (PINC & 0x04); break; }
case 6 : { byte_1 |= (PINC & 0x02); break; }
case 7 : { byte_1 |= (PINC & 0x01);
// if(column_counter_byte_1 < sizeof(columns_byte_1) )
// {
columns_byte_1 [column_counter_byte_1] = byte_1;
//columns_byte_1 [2] = byte_1;
column_counter_byte_1 += 1;
if (column_counter_byte_1 == 240) { column_counter_byte_1 = 0; }
// }
break;
}
case 8 : { byte_2 |= (PINA & 0x80); PORTD |= (1 << PIND4); PORTD &= ~(1 << PIND3); break; }
case 9 : { byte_2 |= (PINA & 0x40); break; }
case 10: { byte_2 |= (PINA & 0x20); break; }
case 11: { byte_2 |= (PINA & 0x10); break; }
case 12: { byte_2 |= (PINA & 0x08); break; }
case 13: { byte_2 |= (PINA & 0x04); break; }
case 14: { byte_2 |= (PINA & 0x02); break; }
case 15: { byte_2 |= (PINA & 0x01);
// if(column_counter_byte_2 < sizeof(columns_byte_2) )
// {
columns_byte_2 [column_counter_byte_2] = byte_2;
//columns_byte_2 [2] = byte_2;
column_counter_byte_2 += 1;
if (column_counter_byte_2 == 240) { column_counter_byte_2 = 0; }
// }
break;
}
case 16: { byte_3 |= (PINB & 0x80); PORTD &= ~(1 << PIND4); break; }
case 17: { byte_3 |= (PINB & 0x40); break; }
case 18: { byte_3 |= (PINB & 0x20); break; }
case 19: { byte_3 |= (PINB & 0x10); break; }
case 20: { byte_3 |= (PINB & 0x08); break; }
case 21: { byte_3 |= (PINB & 0x04); break; }
case 22: { byte_3 |= (PINB & 0x02); break; }
case 23: { byte_3 |= (PINB & 0x01); PORTD |= (1 << PIND7);
// if(column_counter_byte_3 < sizeof(columns_byte_3) )
// {
columns_byte_3 [column_counter_byte_3] = byte_3;
//columns_byte_3 [2 ] = byte_3;
column_counter_byte_3 += 1;
if (column_counter_byte_3 == 240) { column_counter_byte_3 = 0; }
// }
break;
}
case 24:
{
PORTD &= ~(1 << PIND7);
BitCounter = 0;
start_scan = 0;
byte_1 = 0;
byte_2 = 0;
byte_3 = 0;
break;
}
} // from: switch
} // from: ISR
int main(void)
{
DDRA = 0b00000000;
// PORTA = 0b11111111; // have to be out for the correct working
DDRB = 0b00000000;
PORTB = 0b11111111; // have to be out for the correct working
DDRC = 0b00000000;
// PORTC = 0b11111111; // have to be out for the correct working
DDRD = 0b11111110; // PD0 = RXD
// PORTD = 0b00000001;
sei();
TCCR1B |= (1 << WGM12); // CTC-mode,
TIMSK |= (1 << OCIE1A); // timer1 A compare match interrupt enabled
OCR1A = 32000; // 4mS
UCSRA = (1 << MPCM); // enable: multi processor communication mode
UCSRB = (1 << RXEN) | (1 << TXEN)| (1 << UCSZ2); // Turn on the transmission and reception circuit
UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // 9-bit mode, URSEL bit for selecting UCSRC
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
for(;;)
{
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
receivedbyte = UDR; // Fetch the received byte value into the variable "ReceivedByte"
//*** adress numbering: TSAL 1-20 and TSOP 21-40 *******************************************************
if (receivedbyte == 25) // adress byte
{
UCSRA &=~(1 << MPCM); // make MPCM "0"
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
receivedbyte = UDR; // Fetch the received byte value into the variable "ReceivedByte"
if (receivedbyte == 0b11110000) // is the data byte: start your scan
{
// PORTD |= (1 << PIND4); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
start_scan = 1;
}
if (receivedbyte == 0b00000001) // is the data byte: send the data 1e byte to the master
{
_delay_ms(5);
start_send_data_byte_1 = 1;
}
if (receivedbyte == 0b00000010) // is the data byte: send the data 2e byte to the master
{
_delay_ms(5);
start_send_data_byte_2 = 1;
}
if (receivedbyte == 0b00000011) // is the data byte: send the data 3e byte to the master
{
_delay_ms(5);
start_send_data_byte_3 = 1;
}
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
receivedbyte = UDR; // Fetch the received byte value into the variable "ReceivedByte"
if (receivedbyte == 0b11111111) // is the stop byte
{
UCSRA = (1 << MPCM); // enable: multi processor communication mode
}
}
//********** TSOP ****************************************************************************************
while (start_scan == 1)
{
TCCR1B |= (1 << CS10); // start timer with prescaler = 0
if (column_counter_byte_1 == 239) //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
PORTD |= (1 << PIND7); // for checking groen = "1" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
}
if (start_scan == 0)
{
TCCR1B &= ~(1 << CS10); // stop timer with prescaler = 0
}
while (start_send_data_byte_1 == 1)
{
PORTD |= (1 << PIND3); // for checking rood = "1" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PORTD |= (1 << PIND2); // switch MAX485 as transmitter pin 2 & 3 = "1"
for (shift_byte_out = 0; shift_byte_out < 302; shift_byte_out ++)
{
while ((UCSRA & (1 << UDRE)) == 0) {}; // do nothing till the UDR is ready to receive
bytetosend = columns_byte_1[shift_byte_out];
UDR = bytetosend;
}
start_send_data_byte_1 = 0;
PORTD &= ~(1 << PIND3); // for checking rood = "0" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
while (start_send_data_byte_2 == 1)
{
PORTD |= (1 << PIND4); // for checking geel = "1" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PORTD |= (1 << PIND2); // switch MAX485 as transmitter pin 2 & 3 = "1"
for (shift_byte_out = 0; shift_byte_out < 302; shift_byte_out ++)
{
while ((UCSRA & (1 << UDRE)) == 0) {}; // do nothing till the UDR is ready to receive
bytetosend = columns_byte_2[shift_byte_out];
UDR = bytetosend;
}
start_send_data_byte_2 = 0;
PORTD &= ~(1 << PIND4); // for checking geel = "0" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
while (start_send_data_byte_3 == 1)
{
PORTD |= (1 << PIND7); // for checking groen = "1" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PORTD |= (1 << PIND2); // switch MAX485 as transmitter pin 2 & 3 = "1"
for (shift_byte_out = 0; shift_byte_out < 302; shift_byte_out ++)
{
while ((UCSRA & (1 << UDRE)) == 0) {}; // do nothing till the UDR is ready to receive
bytetosend = columns_byte_3[shift_byte_out];
UDR = bytetosend;
}
start_send_data_byte_3 = 0;
PORTD &= ~(1 << PIND7); // for checking groen = "0" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
if (start_send_data_byte_3 == 0)
{
PORTD &= ~(1 << PIND2); // switch MAX485 as receiver pin 2 & 3 = "0"
}
} // from: for (;;)
} // from: main
benleentje
Golden Member
char *p = buffer;Een char declareren = ASCII declareren
Dit vraag ik meer aan de rest.
Als je dit al in je code zet dan ga je er toch al vanuit dat er ASCII binnenkomt. En heeft dat effect op de verdere verwerking van de data?
SparkyGSX
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Elke keer dat je data leest gooi je potentieel een karakter weg, waardoor alles daarna verschuift, en dat hele stuk rond Q1 t/m Q15 slaat helemaal nergens op.
Dit is wat CrapGPT maakt. Ik gebruik zelf ook regelmatig AI code generatie, maar ik kan het lezen, begrijpen, en de fuckups eruit halen. Het is een illusie dat je AI iets kunt laten maken wat je zelf niet begrijpt, en dat iets zinnigs uit gaat krijgen.
[Bericht gewijzigd door SparkyGSX op (45%)]
Op dinsdag 6 januari 2026 18:47:21 schreef SparkyGSX:
Ik gebruik zelf ook regelmatig AI code generatie, maar ik kan het lezen, begrijpen, en de fuckups eruit halen
dat maakt inderdaad een groot verschil.
die laatste code gemaakt in atmel studio voor de atmega32 is niet zo heel moeilijk.
maar het lijkt wel wanneer ik code in VS code op een rasperry pi maak, het een heel stuk ingewikkelder oogt, (nu doe ik dat voor het eerst, dat scheelt ook natuurlijk) en ik maak ook voor het eerst gebruik van chatGPT
de data komt nu binnen over een USB poort, word het eenvoudiger wanneer ik die binnenhaal over een UART ?
dat verwacht ik zelf eigenlijk wel.
[Bericht gewijzigd door trix op (15%)]
SparkyGSX
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Nee dat is allebei gewoon een bytestream, het maakt niet uit of het een echte seriële poort is of een virtuele over USB.
Op dinsdag 6 januari 2026 18:45:05 schreef benleentje:
char *p = buffer;Een char declareren = ASCII declareren
Dit vraag ik meer aan de rest.
Als je dit al in je code zet dan ga je er toch al vanuit dat er ASCII binnenkomt. En heeft dat effect op de verdere verwerking van de data?
Dat klopt wel op zich, maar dat is meer een hint naar de programmeur en niet naar de compiler. Voor de compiler is een char hetzelfde als een byte, en -afhankelijk van compiler vlaggetjes- die kan signed of unsigned zijn.
Ik vind die code voor de AtMega32 wel vreemd.
De timer interrupt schrijft zijn data weg in columns_byte_1, en later wordt de data verstuurd vanuit een andere array columns_byte_11. En zo heb je ook arrays columns_byte_2 / columns_byte_21 en columns_byte_3 / columns_byte_31.
Dus de data die verstuurd wordt komt uit arrays die nooit worden geschreven.
Maar de data in die arrays is niet in ASCII, en er is ook nergens een ASCII conversie te vinden, dus dan kun je nooit ASCII binnenkrijgen op de Raspi.
En ik zie ook dat je index waarden 0 t/m 21 gebruikt op een array met 20 waarden. Dus alles boven index 19 kan een beetje vreemd resultaat geven.
for (shift_byte_out = 0; shift_byte_out <= 21; shift_byte_out ++) {
bytetosend = columns_byte_21[shift_byte_out]Kijk eens op je pi wat er nu echt uit die atmel binnenkomt. Bijvoorbeeld met
cat /dev/ttyUSB67 | xxd
Stoppen met control-C. xxd maakt een hexdump.
Eventueel doe je dit nadat je je programma al geprobeerd hebt, de seriële poort blijft staan in de laatst gebruikte modus.
het lijkt er op dat die columns_byte_11 array met de hand is toegevoegd voor test doeleinden.
dan is dit dus niet de versie die in de atmega32 zit, maar in de controller zit dan een versie die wel vanuit columns_byte_1 de data naar buiten stuurt.
maar dan zit er dus geen ascii conversie in de code.
blurp zal ik morgen eens proberen.
maar ik ben er zo goed als zeker van de het gewoon raw data is.
[Bericht gewijzigd door trix op (14%)]
De logic analyser laat ook een stream 0x00 bytes zien. Alle bits op nul, dus geen ascii, wbt net stuk dat zichtbaar is.
Dus nu ben ik wel benieuwd wat er uiteindelijk in de file op de raspberry terechtkomt. Kun je dat eens laten zien?
ja,.. maar dat word morgen, als ik in de schuur ben
(zoals ik al eerder zij is de raspberry niet "verbonden" met dropbox).
edit: ik heb de code voor de atmega32 vervangen voor de juiste versie (zonder de test array's).
SparkyGSX
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Op dinsdag 6 januari 2026 18:45:05 schreef benleentje:
char *p = buffer;Een char declareren = ASCII declareren
Nee, een char is simpelweg een integer van ten minste (en meestal, maar niet altijd) 8 bits.
ASCII bestaat niet totdat je iets met string functies doet.
buckfast_beekeeper
Van Lambiek wordt goede geuze gemaakt.
Je hebt 23 keer op rij 0x00. Dat geeft al 184 keer 0. Daarna heb je 0x0F. Dat is 0000 1111 binair. Of decimaal 15. Dus na 188 keer een 0 ga je 4 keer een 1 vinden. In je 2de lijn vind je dan ook 4 keer een 1 gevolgd door 4 keer 0 en weer 4 keer 1. Je gaat van de losse bits bytes (8bits) en words (2bytes) moeten maken. Begin je niet correct is alles wat volgt fout.
ik begrijp het niet volledig maar de byte versie is zoals het binnenkomt in de raspberry pi 5 en de bits versie is daar uit "afgeleid" en niet andersom,....of bedoel je dat niet ?
Ik vind het toch vreemd allemaal.
De AtMega32 verstuurt niks als hij geen commando binnenkrijgt. En de Raspberry verstuurt geen commando, dus dan zou er niks kunnen gebeuren.
Maar als de Mega32 wel een commando zou krijgen dan verstuurt hij zijn data in blokken van 302 bytes. En die data wordt binair verstuurd. Niks geen Ascii.
Maar toch krijgt de Raspberry data binnen in ASCII gecodeerd, en uit elke 2 Ascii-Hex characters maakt die dan één byte om in de text-file te schrijven. Dat doet hij dan 1000 keer (TARGET_BYTES). Maar ik zie zo gauw niet waar die ASCII data vandaan komt. Normaal zou die uit de AtMega32 moeten komen, maar dat zie ik hier niet terug in de code.
benleentje
Golden Member
Op woensdag 7 januari 2026 16:52:18 schreef trix:
de files geopend in kladblok:
het zijn 1000 bytes (dat aantal "haal ik ook binnen" in de raspberry
Maar hoeveel bytes heeft de atmega verstuurd want dat moeten er dan ook 1000 zijn.
Een startpost goed doorlezen is toch wel moeilijk voor mij. En ik heb belangrijke info daar gemist
het probleem waar ik tegen aan liep was dat op een of andere manier de data vaak werd geinterpeteerd als ascii.
dat kwam iedere keer terug bij het vragen in chatGPT, en bij mijn eigen testen.
dan werd 0x00 binair 0,0,1,1,0,0,0,0,0,0
Hij maakt dus ergens van 8 bit ineens een 10 bit waarde. Maar die waarde zelf heeft niks met ASCII te maken.
Maar andersom klopt het wel
Jij stuurt 0x00 via de UART/USB en de Software die het ontvangt die weet niet wat ermee te doen
ASCII CHR(0)
verwijst naar de Null karakter (NUL), de allereerste controlecode in de ASCII-tabel, vertegenwoordigd door het getal 0, die wordt gebruikt als een speciale, niet-afdrukbare tekst-terminator of 'tekst-kwalificatie', maar vaak onvoorspelbare resultaten geeft omdat het programma's vaak gebruiken als een teken dat het einde van een tekenreeks aangeeft, zoals in C-strings
IS dit het enige karakter die verkeer ging of ging er meer verkeert. Want alle Waardes 0 tm 32 hebben een speciale betekenis.
Oplossig is zoals eerder gezegd om de uart/USB ontvanger in binaire mode te zetten
Op woensdag 7 januari 2026 19:45:41 schreef deKees:
De AtMega32 verstuurt niks als hij geen commando binnenkrijgt. En de Raspberry verstuurt geen commando, dus dan zou er niks kunnen gebeuren.
nee wacht,...dit is niet het volledig plaatje, er zit nog een controller tussen. de raspberry en de atmega 32 hangen niet direkt aan elkaar.
het ging mij meer om het ascii gebeuren, maar met deze 2 losse delen (atmega32 en raspberry) overzie je het totaal niet.
ik had niet meteen door dat je die datastroom aan mekaar wou linken 
dat gaat zo ook niet. dan moet ik een totaal overzicht maken.
dan komt er weer een stuk code bij die in een AVR128DB48 draait.
ik ben bang dat we dan weer snel afdwalen v/d eigenlijk vraag. op zich niet erg daar is ook veel van te leren.
hier ben ik al best wel lang mee aan het spelen, en iedere keer bedenk ik wat anders en ga ik daar mee aan de slag.
het gaat mij ook niet om het einddoel maar meer om het bouwen/proberen/testen/pionieren. de meeste bouwen dan 5 losse projecten, maar ik doe dat op 1 project, omdat daar veel aspecten van electronica/programeren en mechanica inzit.
ik zal de "dataflow" waar ik het hier over heb eens optekenen.
dit is de data flow waar ik het in dit topic over heb. maar het totaal is veel groter.
[attachment=1]
en de code in de AVR128DB48 heb ik hier nog niet gepost, en die heb je dus wel nodig om te kunnen zien of er ergens eens ascii conversie in zit.
ik wil wel de volledige code posten, maar die is 800 regels (ik weet het dat valt nog wel mee) maar nog onder constructie.
ik zal eerst eens kijken of ik die delen eruit kan halen die voor de in en uitgaande dataflow zorgen.
ik zit net die code in de AVR128DB48 eens te bekijken, en ik ga nu twijfelen of de data toch niet ascii verstuurt word naar de raspberry......
ik zie dit stukje code (heb ik zelf gemaakt een paar maanden terug) en dat kon wel eens een ascii conversie zijn ? (toen stuurde ik de data naar een laptop)
ik zal morgen met de LA een printscreen maken v/d dataflow tussen de AVR128DB48 en de raspberry pi 5.
alvast bedankt voor je geduld en excuses voor de eventuele verwarring die ik wellicht gecreëerd heb.
// **************************************************************************************
// ***** USART 1 DATA TO PC *************************************************************
// **************************************************************************************
void USART1_init(void) // data to PC init
{
// Set baud rate: 9600 for 4 MHz clock
// Formula: BAUD = (f_CPU * 64) / (16 * baud) - 1
// Use fractional mode (recommended)
// USART2.BAUD = (uint16_t)( (float)64 * 4000000 / (16 * 9600) + 0.5 );
USART1.BAUD = 1667;
PORTC.DIRSET = PIN0_bm; // Set TX pin (PC0) as output
USART1.CTRLB = USART_TXEN_bm; // Enable TX
USART1.CTRLC = USART_CHSIZE_8BIT_gc; // Set frame format: 8 data bits, no parity, 1 stop bit (default)
}
int USART1_putchar(char c, FILE *stream) // data to PC printf
{
if (c == '\n') {
USART1_putchar('\r', stream); // add carriage return before newline
}
while (!(USART1.STATUS & USART_DREIF_bm)); // Wait for buffer
USART1.TXDATAL = c;
return 0;
}
FILE usart1_stdout = FDEV_SETUP_STREAM(USART1_putchar, NULL, _FDEV_SETUP_WRITE);
// Redirect printf to USART1
Wel, daar zit de conversie nog niet. Maar het lijkt er wel op dat de interface hier in ASCII is. Het lijkt erop dat je printf() gebruikt en die doet inderdaad conversie.
ja zo'n vermoede had ik al een klein beetje, morgen de LA eens laten kijken of ik kan achterhalen wat er nou precies verstuurt word.
het zou wel het een en ander voor mij kunnen verklaren.
buckfast_beekeeper
Van Lambiek wordt goede geuze gemaakt.
5x ATmega die gegevens naar 1 plek sturen. Kan je dan niet veel eenvoudiger RS485 gebruiken? RPi als master en alle ATmega als node? RPi vraagt dan sequentieel aan elke ATmega of die iets te vertellen heeft. Zo ja wordt dat binnen genomen. Zo neen, op naar de volgende.
Alles wat tussen startpunt en eindpunt zit is extra ballast en kan ook weer programmeerfouten bevatten. Al zeker als programmeren nog veel vragen oproept.
Is 1667 een veel toegepaste baudrate? Daar zou ook nog een communicatie probleem kunnen zijn. Zelfs 2400Bd is nog heel weinig. Met een goede programmering en goede verbindingen zou 38400 of 19200Bd toch moten gehaald worden.
[Bericht gewijzigd door buckfast_beekeeper op (21%)]
// Set baud rate: 9600 for 4 MHz clock
// Formula: BAUD = (f_CPU * 64) / (16 * baud) - 1
Dus 1667 is de waarde voor 9600 baud.