avr veel variabelen opslaan ?

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

Op 3 mei 2020 11:32:16 schreef trix:
..
die 3 databytes worden in de tsops opgeslagen (worden er 900 tot.)
en naar de master gestuurd als die daar om vraagt.
[...]

Ja, omdat de scantijd zo hoog is ben je bijna verplicht om het zo te doen.

LDmicro user.
trix

Golden Member

3 bytes per TSOP PCB (1x atmega 16)
12x TSOP PCB
300 x scannen
3x12x300 = 10800 bytes

dus uiteindelijk zitten er straks 10800 bytes in de ext. RAM. die vertegenwoordigen een raster (matrix) van 3x3 mtr. waarin het werkstuk met allemaal "1"-en.
aan de hand van die data wil ik dus de steppers sturen om het werkstuk na te tekenen.

ik verwacht geen cheksum o.i.d. dergelijks nodig te hebben, omdat ik weet dat bepaalde bit combinaties onmogelijk zijn. dus ergens 1,2 of 3 losse "1"-en negeer ik, ik heb dit al eens eerder filteren genoemd. mischien voldoet dit niet aan de verwachting, dan moet er een cheksum komen.
de data overdracht over de RS485 gaat relatief langzaam (9600 boud), de kabel is kort ( 5-10 mtr.) verwacht daar ook geen "corupte" bytes van.

wat ik al eerder heb gezegd: het project is redelijk groot, maar zeer goed in te delen in blokken die na elkaar moeten worden afgehandeld. bijna niets gaat tegelijk.
van een zo'n blok ben ik achter gekomen dat er wel meerdere dingen tegelijk moet gaan, is voor nu nog geen probleem, maar gaat het later denk ik wel worden. en dat zijn de steppers, gaan nu nog 1 voor 1 maar moeten met meerdere tegelijk kunnen, volgens mij heeft stijnos in een topic van mij ooit iets over gepost, hoe dit normaal gaat.

als je een machine wilt programeren kan je inderdaad het best vooraf volledig in kaart brengen hoe je dit gaat doen, maar dan moet je (dus ook vooraf) veel kennis van programeren hebben,...en die heb ik dus niet,....bij mij is het meer "trail & error". geluk is dat het allemaal blokken zijn zodat ik het overzicht nog wel kan houden. en omdat ik julie af en toe iets mag vragen, gaat het wel lukken _/-\o_
bovendien zal een goede programeur in sommige gevallen denken:....ja het werkt zo wel, maar ik kan het beter zo en zo doen want mischien willen ze nog ooit iets toevoegen.....is bij mij niet aan de orde. dus b.v. de ext. RAM schrijven van uit de UAST ISR,.....wat "quick & dirty" is voldoet voor mijn toepassing.

eigenwijs = ook wijs

Op 3 mei 2020 12:54:38 schreef trix:
ik heb dit al eens eerder filteren genoemd. mischien voldoet dit niet aan de verwachting,

Dit heet "salt and pepper filtering".

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

Golden Member

eigenwijs = ook wijs

Op 3 mei 2020 09:16:14 schreef henri62:
[...]
Het is ook de bedoeling dat trix er iets van leert, dus niet nu al met hele slechte dingen aankomen.

Die hoop heb ik stilletje een beetje opgegeven en probeer nu vooral met parktische oplossingen. Dan maar minder netjes. Er is niet de intentie om een volwaardig firmware engineer te worden begrijp ik :)

Anyway ik bedacht me gisteren nog iets, wat je zou kunnen helpen om het wat netter te maken Trix.
Ik gebruikte jaren geleden op de AVR een uart library van Peter Flury
https://github.com/damadmai/pfleury)
(je hebt enkel uart.c en uart.h nodig dacht ik)
Daarin zitten de ISR's die de uart data al automatisch in een ring buffer zetten.
In je mainloop kijk je continu met een

code:

 uin8_t data = uart_getc();
if (data != UART_NO_DATA) {
 SPI_Transfer(data);
//of wat nog meer
}

Zo hou je het schrijven in de spi RAM toch netjes buiten de interrupt.

Arco

Special Member

Normaal gesproken lijkt me het laden van de SPI in de UART interrupt toch de beste manier. (op een meer geschikte processor na dan... ;) )

De snelheid staat of valt met hoe efficient die compiler je code omzet naar assembly.
Ik zou voor SPI geen library gebruiken en die paar regels direct inkloppen; ik schat dat dat 4x zo snel (of meer) is...
Dat scheelt je in ieder geval een call en return bij iedere interrupt.

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

Golden Member

mischien dat ik het begrip ringbuffer niet goed begrijp, maar volgens mij heb ik daar niks aan. ik moet gewoon in 1x 10800 bytes v/d atmega16 (TSOP) over de UART naar de atmega 2560 en dan in de ext. RAM, liefst zo snel mogelijk.

Op 4 mei 2020 07:47:44 schreef Stijnos:
[...]
Er is niet de intentie om een volwaardig firmware engineer te worden begrijp ik :)

ik ga inderdaad geen cariere switch doen, heb ik de leeftijd ook niet meer voor :)

mag ik dit nog een keer onder de aandacht brengen:

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
Arco

Special Member

Een ringbuffer is wel de beste (netste) oplossing maar geeft overhead.
Zoals ik in mijn vorige post vermeldde is het laden van de SPI in de UART-rx interrupt het snelste. (lieftst zonder libraries)

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

Op 4 mei 2020 10:16:18 schreef Arco:
(op een meer geschikte processor na dan... ;) )

Precies. Er worden problemen gecreerd door domme keuzes aan het begin. Voor een tientje heb je een "master" controller met genoeg geheugen voor 13000 plaatjes van 19kb. En dan moet er hier het schrijven naar SPI ram in een interrupt geprutst worden omdat iemand data van interrupt naar main doorgeven niet aan de praat krijgt....

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

Special Member

Daar gaat het niet om: doorgeven van interrupt naar main en vandaar weer naar spi geeft veel onnodige overhead...
Direct alles in de interrupt afhandelen is veel sneller. (zeker bij hogere baudrates als bijv. 115k2)

Je moet met een kleine controller nu eenmaal roeien met de riemen die je hebt... ;)

[Bericht gewijzigd door Arco op maandag 4 mei 2020 18:48:49 (17%)

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

RAM geheugen is niet gedefinieerd na opstarten. Daar staat meestal random data totdat er iets wordt geschreven.

trix

Golden Member

ok, ik dacht ergens gelezen te hebben dat er overal 0xFF staat :X
kan ook eigenlijk niet, nu ik er over nadenk.

keuze v/d proccesor is natuurlijk in het begin gemaakt, gebaseerd op hetgeen wat ik kende, en dat was niet veel ;)
maar het voldoet aan alles eisen die ik had, behalve te weinig RAM. en die is eenvoudig uit te breiden.
er zullen wel proccesors zijn die sneller en beter zijn, met ik weet wel niet hoeveel RAM. maar ik heb dat niet nodig, 13000 plaatjes opslaan ? totaal nutteloos voor deze toepassing. alsof je met een ferrari boodschappen gaat doen.

ik vind natuurlijk ook wel, dat je voor het moderne snelle spul moet kiezen. maar ik kende het gewoon niet, en wat ik wel kende voldeed, en nu is er geen echte noodzaak om over te stappen.

[Bericht gewijzigd door trix op maandag 4 mei 2020 20:12:57 (74%)

eigenwijs = ook wijs

Op 4 mei 2020 19:59:59 schreef trix:
ok, ik dacht ergens gelezen te hebben dat er overal 0xFF staat

Dat is flash. Lege flash begint met 0xff.

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

Golden Member

dan was ik daar mee in de war, tnx

eigenwijs = ook wijs