avr veel variabelen opslaan ?

Als je hele systeem vastloopt als er eens een keer een byte kapot gaat, lijkt het me geen handig ontwerp. Ik zou iets maken dat je zegt van de master: "Doe de eerste 100 bytes?".

De slave stuurt dan die 100 bytes, met een checksum. In de eerste instantie controleer je de checksum en doe je d'r verder niets mee (rood ledje aan).

Als dat rode ledje aan blijkt voor te komen kan je dingen gaan doen. Signaal verbeteren of slave nog eens vragen om die 100 bytes.

De slave is dan lekker "slave"! Die hoeft niet te bedenken welke 100 bytes te sturen, gewoon doen wat de master vraagt. Dan kan je later ook gewoon in de master dingen als een "retry" implementeren.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Op 27 april 2020 21:21:09 schreef trix:
ik zit ook net te bedenken: nu doe ik in een keer 900 bytes.
maar ik kan dat ook simpel opsplitsen in 3x300 bytes.
ik ben nu bezig om dat op te splitsen in de master (van 1x900 naar 3x300). maar als ik dat gewoon in de slave doe, krijg je een kortere "package", nog minder kans op storingen lijkt me.

En meer pakjes waarin een storing kan optreden.

Zonder checksum maakt niet echt uit of je 1x900, of 3x300 bytes verstuurt.

Met checksum heb je bij 1x900 iets meer kans dat twee fouten elkaar opheffen, en dus niet gezien worden.

Als je voldoende bandbreedte hebt kun je de truuk van DMX512 gebruiken. Alle 900 bytes steeds herhalen, en als je 2(3,4 kies maar) keer dezelfde hebt ontvangen is die geldig en pas je de dimstand van de lamp aan.

bprosman

Golden Member

In het verleden heb ik dit (protocol) een paar keer toegepast.
Zit leuk in elkaar, en volledig uitgewerkt.
Helemaal zonder error check zou ik niet doen.

http://www.hth.com/snap/

[Bericht gewijzigd door bprosman op dinsdag 28 april 2020 16:28:29 (15%)

De jongere generatie loopt veel te vaak zijn PIC achterna.
trix

Golden Member

zo'n cheksum, hoe werkt dat ongeveer ?

eigenwijs = ook wijs
Arco

Special Member

Simpelste checksum is alle bytes (behalve die van de checksum zelf) bij elkaar optellen en dat versturen als modulo 0x100 byte. (of 2 bytes: modulo 0x10000)
Als je meer zekerheid wilt kun je een CRC-checksum nemen, da's wel een stukje gecompliceerder...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Gewoon alles bij mekaar optellen en de 16 bits versturen wordt ook wel gedaan.

Dit simpele optellen heeft tot nadeel dat als er twee bitfouten optreden je niet zeker weet of dit gedetecteerd wordt. Bijvoorbeeld byte x moet zijn: 16, bit drie gaat van 0->1, dus wordt het 24. Byte y moet zijn 73, bit drie gaat van 1 -> 0 dus wordt het 65. De som is in beide gevallen 89.

Hier staat (in het antwoord) een werkende CRC16 functie:
https://stackoverflow.com/questions/10564491/function-to-calculate-a-c…
Zo moeilijk is het niet.

Volgens mij is het dan wel zeker dat je 2 bitfouten altijd detecteert. Hmm. Dat kan niet het geval zijn als je checksum over meer dan 256 bits loopt.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Je hebt bij een checksum controle ook iets dat het geheel overziet en eventueel de waarden terug opvraagt en een storing geeft als het niet lukt.

Errordetectie kun je doen bij een update, want zolang het niet werkt ben je beter af bij een zo eenvoudig mogelijke oplossing en programma.

De opstelling werkend krijgen is nu het focuspunt denk ik.

LDmicro user.
trix

Golden Member

dat is zeker zo.
nog eens over nagedacht, maar ik denk ook niet dat ik een checksum nodig heb. als er bij mij ergens een bitje verkeerd komt te staan, "filter" ik dat er al uit. omdat ik weet dat de minimale breedte in het werkstuk ca. 80 mm is, kan b.v. een "1" omgeven door allemaal een "0" nooit voorkomen, dus dat word ook een "0". zo zijn er meerdere van dit soort controles uit te voeren.
dus ik ge even zonder checksum verder, ik denk dat ik er mee weg kom.

eigenwijs = ook wijs
trix

Golden Member

hallo, daar ben ik weer :)

het lijkt er op op dat de in de externe RAM komt te staan, maar ik zou dat graag willen kunnen controleren. dat is nu makkelijk, maar ook later als alles klaar is.
nou wou ik daar het display voor gebruiken. als ik daar het adres invoer dat dan de bij behorende byte word getoond.
nou zie ik niet hoe je op een eenvoudige manier een byte binair op het display kunt krijgen. je kan eigenlijk alleen maar "harde" karakters er naar toe sturen.
dat zou ik met een switch/case kunnen doen, maar dan heb je 256 cases, lijkt mij nogal omslachtig.
hoe zou je dit eenvoudiger kunnen doen ?
display is met een hd44780.

eigenwijs = ook wijs
Arco

Special Member

Je kunt toch de waarde gewoon in hex tonen? Voor testen van ram worden vaak de patronen 0x55 (01010101) en 0xAA (10101010) gebruikt.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Zoiets als dit,
Wel aanpassen aan je display library.

code:


char HexDigit(uint8_t c)
{  c &= 0x0F;
   if(c > 9)
   {  // 0x0A .. 0x0F --> 'A' .. 'F'
      return 'A' + (c - 10);
   }
   else
   {  // 0x00 .. 0x09 --> '0' .. '9'
      return '0' + c;
   }
}


// Write 2 HexDigits
void WriteHexByte(uint8_t Data)
{  WriteChar(HexDigit(Data >> 4));
   WriteChar(HexDigit(Data >> 0));
}

trix

Golden Member

Op 1 mei 2020 13:12:30 schreef Arco:
Je kunt toch de waarde gewoon in hex tonen? Voor testen van ram worden vaak de patronen 0x55 (01010101) en 0xAA (10101010) gebruikt.

ja,. dat is een eenvoudige 1e test, om te kijken of het read/write werkt. maar ik wil kijken of de verwachte data v/d scanner ook daad werkelijk in de ext. RAM zit.

dekees, ga ik bekijken, ziet er niet simpel uit. dit moet toch niet toegevoegd worden aan de display libary ?

eigenwijs = ook wijs
Arco

Special Member

Je bent wel erg achterdochtig... ;)
Ik heb al heel veel applicaties gemaakt, maar eigenlijk nooit teruggelezen na een write of de waarde klopt. Als je programma deugt gaat dat nooit mis.
Met de 'checkerboard test' kun je de integriteit van de ram zelf testen.

Voor belangrijke stringwaardes zet ik er een checksum achter.
(er kan wel eens een bitje omvallen in de loop der jaren tenslotte, al heb ik dat ook zelden meegemaakt)

Die compiler zal toch standaard wel iets hebben om hex strings te maken? (dat heeft iedere compiler wel die ik tot nu toe gebruikt heb...)

[Bericht gewijzigd door Arco op vrijdag 1 mei 2020 13:34:15 (14%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ja en Nee. Je moet iets gebruiken als snprintf(buffer, size , "%02x", getal) of afgeleide, allemaal een vrij grote bak library code.

Dus wat deKees heeft opgegeven is prima en mooi compact. Zoiets doe ik ook meestal als het klein moet zijn.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
trix

Golden Member

ik ben weer een stukje verder,
ik heb op de ext. RAM een LA signaal gemaakt op de SS (slave select) en op de SI (seriel input).

in de TSOP (atmega 16 slave) heb ik een array gemaakt met daarin 1,2,3,..t/m...20
vanuit de hoofd PCB (atmega 2560) geef ik een comando: TSOP send me your data, en de array word naar buiten geschoven.

op de LA zie ik keurig:
- de SS "0" worden
- gevolgd door: 0b00000010 = "write data to memory"
- dan: 3 bytes = adres klopt met de door mij mee gegeven adres = 1000
- dan: 26x 0b11110000 weet even niet zeker waar die vandaan komen
- MAAR DAN: 6x byte met 1, 6x byte met 2, 6x byte met 3 enz.enz.
(die 6x is af en toe 7x.)

omdat de UART v/d slave->master langzamer is, dan de SPI van de atmega 2560->ext.RAM.
lijkt het er op dat de SPI 6 of 7 keer dezelfde byte verstuurt.
maar ik zie niet hoe dit te voorkomen. wellicht met een interrupt ?
of moet je zelf ergens bij houden dat je een byte al verstuurd hebt ?
wat code erbij hoe ik het gedaan heb, de data vanaf de TSOP (slave) word in een interrupt in een variabele gezet: receivedbyte
die ik weer meteen naar buiten schuif richting de ext. RAM.

c code:


ISR(USART0_RX_vect) // receving data from TSOP's
{
receivedbyte = UDR0; // copy the received byte value into the variable "receivedbyte	
TSOP_byte_transfer_counter = TSOP_byte_transfer_counter + 1;	
}	

c code:


if (TSOP_request_byte_counter == 1) // asking from TSOP 1e byte
{
	PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
			
	RAM_adress = RAM_adress_temp + 0;
			
	SPI_transfer(0b00000010);  // write data to memory

	address = 1000; // is address in ext. RAM
		
	SPI_transfer((address>>16)); // adress
	SPI_transfer((address>>8)); // adress
	SPI_transfer((address)); // adress											
			
while (TSOP_byte_transfer_counter < 300) // doing loop until 300 bytes are in. ^^^^^^^^^^^^^^^^^^^^
{   
       _delay_us(50); // just for testing		
 				
       SPI_transfer(receivedbyte); // data what you write in the ext. RAM			
								
}
PORTG |= (1 << PING5); // make SS pin ext. RAM = 1				
TSOP_byte_transfer_counter = 0; // if 300 bytes are in make variable "0"
TSOP_request_byte_counter = 2; // read the 2e byte from the TSOP

}
eigenwijs = ook wijs
Arco

Special Member

In dit geval zou je in de UART-rx interrupt gelijk de byte naar SPI kunnen sturen (die is toch sneller)
Ik gebruik altijd een buffer waar de rx bytes in komen, en een andere uart leest ze dan weer in (ik gebruik het om 2 uarts door te linken)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

code:


while (TSOP_byte_transfer_counter < 300) // doing loop until 300 bytes are in.
{   
       _delay_us(50); // just for testing		
 				
       SPI_transfer(receivedbyte); // data what you write in the ext. RAM						
}

Dit gaat niet werken omdat die loop als een kip zonder kop staat te hollen zolang je "TSOP_byte_transfer_counter" < 300 is.
Dus je stuurt dus meerdere dezelfde bytes achter elkaar. (Zoals je zelf ook al gezien hebt, blijkbaar is je SPI write 6x zo snel als je uart ontvangst)

Je moet een synchronisatie maken tussen je ISR en je main loop.
Dat kan op allerlei manieren.

In jou geval wil je denk ik alleen een SPI_transfer(receivedbyte) doen als je EXACT een byte in de ISR hebt ontvangen.

Een simpele oplossing is om de vorige waarde te onthouden en dan een loopje maken die wacht tot de counter veranderd is, dan het byte versturen en de vorige waarde updaten met de huidige.

Zoiets:

code:


int counter_last = 0; // Moet ergens buiten die while loop komen

do {
    // Wacht op ontvangst byte
    while(counter_last != TSOP_byte_transfer_counter) {
        // Burn some time
        _delay_us(50);
    }
    SPI_transfer(receivedbyte);
} while (TSOP_byte_transfer_counter < 300);

(PS ik ga er vanuit dat je TSOP_byte_transfer_counter ook een 'int' is.)

TSOP_byte_transfer_counter en receivedbyte MOETEN volatile gedeclareerd worden!

Normaal gesproken doe je dat met semaphores (als je een O/S hebt). Of met atomic flag operaties. Maar dat gebruik je niet dus moet je het anders oplossen.

-edit- Oh ja, je even goed kijken waar je start bij de ISR, wat is je counter bij start? Is dat 0, dan moet je counter_last ook op 0 beginnen anders is je eerste byte rommel die je in de SPI RAM schrijft. Ik heb het even aangepast in het bovenstaande code block.

Ik bedenk me nu dat er nog een loop omheen moet. Ook dat aangepast.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
trix

Golden Member

ga ik morgen eens proberen, bedankt _/-\o_

eigenwijs = ook wijs

als je zeker weet dat je spi zoveel sneller is als je uart, dan schrijf je die byte toch gelijk via spi in je ram IC als je hem in de uart ISR ontvangt?

Is dat een hele nette oplossing? Nee, maar je hele code hangt zo aan elkaar toch ;) laten we eerlijk zijn.

Je doet nu ook helemaal niks als je een verkeerde byte krijgt of er 1 mist toch?

Arco

Special Member

Zie ook mijn vorige post... ;)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 2 mei 2020 23:13:15 schreef Stijnos:
als je zeker weet dat je spi zoveel sneller is als je uart, dan schrijf je die byte toch gelijk via spi in je ram IC als je hem in de uart ISR ontvangt?

Is dat een hele nette oplossing? Nee, maar je hele code hangt zo aan elkaar toch ;) laten we eerlijk zijn.

Gadverdamme, zie óók mijn vorig post. ALs je straks je SPI transmitter ook onder interrupt wil laten lopen (met fifo buffers oid) dan ga je volledig het schip in.

Je doet nu ook helemaal niks als je een verkeerde byte krijgt of er 1 mist toch?

Maar dat komt er later allemaal nog bij als ik het zo begrepen heb.
Dan kun je alsnog de hele zooi overhoop halen.
Het is ook de bedoeling dat trix er iets van leert, dus niet nu al met hele slechte dingen aankomen.

En die data zal er straks neem ik aan ook weer uit moeten komen.

Het is me ook totaal onduidelijk wat het totaal concept moet gaan worden, geen duidelijke "architectuur" van het geheel en dat is bij dit soort dingen met meerdere controllers etc. wel een "must".
Het uiteindelijke inzicht gaat worden dat je alles opnieuw moet maken en je stukjes code of mechanismes hergebruikt.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
trix

Golden Member

ben nu nog wat aan het testen, ik zal straks uitleggen wat de bedoeling met die data is.

eigenwijs = ook wijs

Op 3 mei 2020 09:16:14 schreef henri62:
...
Het is me ook totaal onduidelijk wat het totaal concept moet gaan worden, geen duidelijke "architectuur" van het geheel en dat is bij dit soort dingen met meerdere controllers etc. wel een "must".
Het uiteindelijke inzicht gaat worden dat je alles opnieuw moet maken en je stukjes code of mechanismes hergebruikt.

Dat werd hier al een paar keren aangehaald.
We lezen mee en ik zie hem verdrinken in de interrupts ;)

Volgens mij moet de master enkel maar aan de rij (24leds/tsops) het startsignaal geven en wachten op 3 databyte's en dan de volgende rij laten starten.
De controllers van de eenzelfde rij IR-leds en de TSOP's moeten dat volledig zelfstandig kunnen afwerken.
Het grootste gedeelte zal de master geen werk hebben en kan die alle binnenkomende data gewoon, zonder dat interrupt gedoe, afhandelen.

LDmicro user.
trix

Golden Member

nou, het is gelukt. ik doe nu inderdaad in de ISR(USART0_RX_vect) de schrijf actie naar de ext. RAM.

ik heb nu op een vrije poort 8x een LED geplaatst om de geheugen plaatsen in de ext. RAM binair te kunnen uit lezen, met 2 drukknoppen kan ik het adres verhogen en verlagen (met de code stuur ik een begin waarde mee nu dus 1000)
nou valt mij op dat de niet beschreven adressen een random waarde bevatten. ik had hier overal 0xFF verwacht ?

eigenwijs = ook wijs
trix

Golden Member

kleine toevoeging, om het volledig te laten kloppen :)

Volgens mij moet de master enkel maar aan de rij (24leds/tsops) het startsignaal geven en wachten op 3 databyte's en dan de volgende rij laten starten.

die 3 databytes worden in de tsops opgeslagen (worden er 900 tot.)
en naar de master gestuurd als die daar om vraagt.

De controllers van de eenzelfde rij IR-leds en de TSOP's moeten dat volledig zelfstandig kunnen afwerken.
Het grootste gedeelte zal de master geen werk hebben en kan die alle binnenkomende data gewoon, zonder dat interrupt gedoe, afhandelen.

eigenwijs = ook wijs