Positions-Display för svarv (AVR)

Berätta om dina pågående projekt.
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Positions-Display för svarv (AVR)

Inlägg av Chribbe76 »

Vi har en support-svarv på jobbet som har en halv-trasig display så jag tar tillfället i akt och bygger en egen.

Orginalet, stor och tung och funktionsmässigt lite för lam.

Bild


I min konstruktion använder jag en ATmega48 och en LCD-display med backlight (Teckenstorleken är egentligen lite för liten men det blir nog bra ändå).
Signalen från linjärskalorna är digital Quadrature där ett steg är 0.01mm.
Funktionen är i grunden enkel, ATmegan läser quadrature och räknar för axel X och Z och skriver ut positionen på displayen.
Det går emellertid att lägga in funktioner som tex verktygsregister(offset) om man vill komplicera det hela (och det vill man).

Nyetsat kort (happy happy).

Bild


Men allt har ju en baksida.

Bild


På vänstra sidan sitter 3st switchregulatorer för att omvandla till +5V, +12V och -12V.
+5V fick en switchreg för att backlighten vill ha ganska mycket ström.
Skalorna drar egentligen inte så mycket +12V men jag vill helst inte värma lådan så mycket så den fick oxå en switchreg.
Att använda en switchreg som kan ge hög ström till -12V är inte alls befogat(skalorna drar nästan ingen ström alls) men jag gjorde så bara för att orginalet kan leverera hög ström.
Signalen från skalorna går via 4 st optokopplare till ATmegan.

Bild
Bild


Lådan är nu bearbetad och försedd med aluminium-fästen för displayen.

Bild


Allt på plats, jag kopplar tanjentbordet via USB-kontakten men jag kommer använda T-bordets PS2-interface.

Bild


Lite synd att lådan blev så repig, jag kanske sprutlackerar den senare.

Bild


Allt är klart, och ATmegan är testad så det som återstår är assembler-programmering och ett monteringsfäste för hela apparaten.
Det här blir mitt första AVR-projekt så jag är inte så haj på processorn ännu men jag ser fram emot att börja med koden på allvar.
Jag undrar:
När jag programmerar Pic brukar jag definiera pinnarna på detta sätt när pinnarna ska användas individuellt: #DEFINE Namn PORTB,3.
I Avr-studio kan man bara definiera ett register eller ett tal, så hur gör ni när ni definierar pinnarna i era projekt :?:
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

Ser ju riktigt snyggt ut! :bravo:

Har inte definierat enskilda pinnar i ASM, däremot i C för AVR GCC har jag gjort så här:

Kod: Markera allt

#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
Sedan så här för att definiera:

Kod: Markera allt

#define Namn PORTC
#define Namn bit_get(PORTD,x)
#define Namn bit_set(PORTD,x)
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Tack Micael!

Dina #define ger inga fel men jag kanske är lite puckad.... kan du(eller någon annan) visa hur man skriver i koden för att ändra en bit i en port med hjälp av ovan nämnda definition (i asm).
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

Chribbe du tänker på att det jag skrev ovan är för C och inte för ASM!!



Kan ju ta ett litet exempel:

Kod: Markera allt

void E_Clock(void)
	{
	//Send command to LCD:
	_delay_ms(10);
	E_LCD; 
	_delay_ms(10);
	E_LCD_OFF;
	}
För att kolla om en bit är satt:

Kod: Markera allt

if(Namn)
{
//Hitta på någon kulig kod.
}

OBS C-kod!!!!
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Jag tror jag lyckades, blev inga fel iaf!

#define bit(p,m) p,m
#define Namn bit(PORTB,3)

För att sätta en bit:
sbi Namn


Tack för hjälpen!
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

Kul att kunna hjälpa till! :)

Lycka till!
Glöm inte att visa hur lyckat det blev.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Fint projekt. Var har du köpt lådan?
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Allt är från Elfa, lådan: 50-194-43
Och kortskenorna: 50-107-56

Jag köpte även denna låda: 50-107-31 som har exakt samma mått, den är dyrare och mycket sämre gjuten så den rekommenderas ej.
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Nu har jag kommit över "tröskeln", koden för displayen fungerade på första försöket.
Skillnaden mellan Pic och Avr är verkligen stor, Avr är mer lik processorn i en "riktig dator" men allt är inte bättre för det.
Jag saknar tex att kunna göra så här:

movlw b'00011111'
iorwf LATB

Med Avr blir det inte lika smidigt eftersom instruktionen OR inte kan komma åt I/O-delen av minnet, då blir det så här:

in R16,PORTB
ori R16,0b00011111
out PORTB,R16

Ja ja, bara en extra instruktion, men det jag ogillar är att om ett interrupt ändrar bit 5-7 i PORTB samtidigt som koden ovan så får man problem, med Pic(jag syftar då på Pic18) har man inte det problemet.

Jag är nybörjare på Avr så jag kan ha missat något, upplys mig isf om det.

Bild
Användarvisningsbild
ucadv
Inlägg: 203
Blev medlem: 29 januari 2007, 23:13:49

Inlägg av ucadv »

cli
in R16,PORTB
ori R16,0b00011111
out PORTB,R16
sei

är ändå 60% snabbare än

movlw b'00011111'
iorwf LATB

om PICen och AVR:et kör på samma klocka :)
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Naturligtvis har du rätt men jag tycker inte man ska tänka på det sättet.

Med Pic18 har man en kristall på 10Mhz och processorn går på "10 MIPS".
Då har den visserligen en 4XPLL inbyggd men för mig som användare är det tämligen ointressant hur processorn jobbar internt.
Att konstruera en processor av den här typen med ett begränsat antal bitar/instruktion är = kompromiss, man kan inte få allt men just nu känner jag att vissa detaljer är lite felprioriterade.

Men visst har jag sagt samma sak om Pic oxå, jag kan nog helt enkelt aldrig bli nöjd med en processor, man får försöka acceptera kompromisserna, eller börja programmera C så slipper man se eländet. :D
Användarvisningsbild
ucadv
Inlägg: 203
Blev medlem: 29 januari 2007, 23:13:49

Inlägg av ucadv »

PICen har fyra normaltillstånd: fetch, read, execute, write-back. varje tillstånd tar en "extern" klockcykel, därför är den interna "exekveringscykeln" 1/4 av den externa.

I en AVR har man en "pipelinad" fetch en cykel före och gör read-execute-write i samma klockcykel. Därför exekverar man en instrktion per klockcykel.

En del instrktioner har en långsam "read" eller kanske en långsam "execute". För att hinna göra allting inom samma klockcykel måste man då...
a) sänka frekvensen
b) dela upp instrktionen i två delar

AVR är mer en beräkningsprocessor än en bit-banger, därför har man valt att offra din atomiska IO-access för att nå högre frekvens.

Det är ännu värre i en snabb ARM7 där kärnan pratar snabb AHB buss som pratar i sin tur med en långsam APB buss som slutligen skriver till IOn. En 60MHz ARM utan FastIO har kanske en toggle-rate på några enstaka MHz :(
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Så det du menar är i princip att Avr'en inte skulle hinna läsa av R-registret och IO-registret för att sen göra or-operationen och sen skicka tillbaka värdet till IO-registret.

Jag kan köpa den förklaringen men varför är det så stor skillnad mellan tex R16 och PORTB, båda är ju uppbyggda av minnesbitar någonstans i chippet?
Användarvisningsbild
ucadv
Inlägg: 203
Blev medlem: 29 januari 2007, 23:13:49

Inlägg av ucadv »

alla register ligger i något som kallas för en "register bank". det är en samling snabba D-vippor & muxar där du kan skriva till ett register och läsa från två andra samtidigt (s.k. dual-port). register banknen ligger fysisk intill ALUn och har en åtkomsttid på max någn ns i en AVR.

IO paddarna ligger däremot utanför kärnan, och är gjorda av långsammare elektronik...



dessutom blir ASIC designen mycket enklare och instruktionavkodningen mycket lättare om man endast tillåter operation mellan register (och konstanter). Detta är klassik load/store arkitektur och grunden för RISC.


http://www.compass-lab.com/pdf/AVR_RISC.pdf
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Intressant läsning ucadv, tack för det.

Det är tydligt att arkitekturen verkligen är optimerad för C och det har dom lagt ner lite mer tid på än en kvart om man säger så.
Men jag sitter fortfarande kvar i assembler-träsket och vet inte riktigt hur jag ska utnyttja processorn.

Med Avr har man 32st interna "general purpose" register som är snabba att använda men dom 16 första kan inte adresseras av instruktioner med konstanter inblandade.
Det går tex inte att: Sätta en bit, lägga en konstant, göra en AND med en konstant osv.
Det som ändå går är att sätta värdet 0 (som visserligen assembleras till en EOR men det spelar ju ingen roll), och man kan testa en bit, öka eller minska med 1, (jag kan ha missat något).
Så 16st register kan man använda till alla instruktioner men 6st av dessa är vigda åt 16-bitars register X,Y,Z som används för tex indirekt adressering.
Det jag vill säga med detta är att registeren inte räcker så långt trots allt eftersom det finns vissa begränsningar.

Avr-folket säger att Pic är skit för att det bara finns 1st internt register(kallat W), men skillnaden mellan Pic och Avr är att Minnet(dom första 256 byten varav 128 byte är general purpose) på en Pic går att adressera direkt för "alla" instruktioner.
Man kan tex sätta en bit, sätta alla 8bitar, göra bit-tester,minska med 1 och givetvis göra vanliga operationer som tex AND och ADD med minnet och W där svaret kan läggas i minnet eller W.
Med Avr Kan man inte göra några operationer alls mot minnet, det går bara att hämta eller lagra vilket dessutom tar 2st klockcykler.

Eftersom det tar tid att flytta data till och från minnet på en Avr måste man använda registren flitigt för att koden ska bli optimal och det upplever jag som stökigt när man anropar subrutiner, risken är ju stor att en subrutin använder ett register som en annan funktion använder.
Detta är inget problem med Pic för man använder alltid minnet och det tar inte slut i första taget.

Kan man få hjälp med detta genom att använda direktiv av något slag som automatiskt reserverar register(tror inte det)?

En lösning är helt enkelt att alla funktioner PUSHar och POPar alla register som kommer förstöras i funktionen men det blir väldigt mycket PUSH och POP som givetvis tar 2st klockcykler eftersom det adresserar minnet.

Hur ska man tänka när man programmerar Avr i assembler helt enkelt?
Eller är det kanske så att en Avr inte bör programmeras i assembler?


Ett svar som tex "Det krävs bara 1 klockcykel/instruktion på en Avr och Pic kräver 4 klockcykler/instruktion så en Avr är alltid snabbare" är onödigt.
Om jag har skrivit något felaktigt så ska ni givetvis påpeka det men annars handlar det här bara om hur man ska åstakomma bästa möjliga programkod på en Avr.
Skriv svar