Programeringsfrågor C++ radiostyrd båt

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Jag håller på att bygga en radiostyrd båt som även kommer utrustas med några sensorer. Eftersom jag är självlärd amatör på programmering känner att jag kommer köra fast på vissa saker när det gäller programmeringen. Kommer därför att fråga mina frågor gällande detta i denna tråd för att slippa skapa en ny för varje nytt problem.
Det kan hända att det blir en byggtråd senare men projektet är ganska långt gånget redan i dagsläget då skrovet snart är färdigt och montering förmodligen kommer ske till helgen. Styrkort, sensorer mm finns färdigt.

Processorn är en 8-bitrars AVR och jag skriver C++ i AVR Studio.

Första frågan som jag undrar är:
Jag har tidigare skrivit ganska välfungerande program men då i princip alltid i en stor fil. Försöker i detta projekt dela upp koden och göra den lite mer universell.
Jag har lite svårt för att förstå hur jag skapar en variabel som kan användas i flera kod-filer. Jag har skrivit en kod för att hantera UART och den funkar, men när jag inkluderar den filen i ett nytt projekt så kan jag ju inte använda variabler deklarerade i UART-filen i min Main-fil. Finns det något enkelt sätt att göra variabler globala över hela projektet? Jag vet att man kan göra det med klasser, men finns det något enklare sätt?
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Micke_s »

extern går att använda i header filen. Så arduino Serial fungerar.

Arduinos lösning är denna lite förenklat.

Kod: Markera allt


HardwareSerial.h
class HardwareSerial
{
public:
 massa uart funktioner
}

extern HardwareSerial Serial;

HardwareSerial0.cpp - här skapas objectet Serial.
HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
Annan lösning kan vara en singleton class.
https://en.wikipedia.org/wiki/Singleton_pattern

Edit: Möjligtvis så tar singleton varianten några byte mer i minne eftersom man skapar en ny pekare till samma objekt.
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Tack :) Är dock inte helt säker på att jag förstod. Vad exakt betyder "extern HardwareSerial Serial;" där?

Men när jag deklarerar denna såhär i H-filen

Kod: Markera allt

extern int bufferIndex;
Så får jag varning: undefined reference to `bufferIndex'
när detta ligger i min UART-fil som inkluderar H-filen

Kod: Markera allt

bufferIndex = 0;
Borde det inte fungera? Vad kan det i så fall vara som gör att jag får den varningen?

Wups: extern talar alltså bara om att den finns deklarerad någon annanstans? Det är ingen deklarering?
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Icecap »

"extern HardwareSerial Serial;" betyder "Det finns en 'HardwareSerial'-klass som heter 'Serial' i projektet. Du ser det inte direkt men den finns! Så använd den om du behöver."

"extern" betyder att den inte är inkluderat i just den fil som deklarerar den som extern - men att den finns i projektet.

Man kan även deklarera an variabel i fil A.c:
t_uint16 EttBraNamn;

och i en annan delfil i projektet behöva "prata" med den variabel:
extern t_uint16 EttBraNamn;

Igen betyder det att 'EttBraNamn' finns någonstans (men inte just i denna fil) och kan användas.

Dock ska man ha klart för sig att det kan skapa problem att okritisk lägga variabler som används här, där och överallt. Det bästa är att separera funktioner så de innehåller de variabler de behöver och i grunden är "self-contained" och sedan kallar man med de variabler som behövs och de rätta svar returneras.

Men ibland kan det göra det hela ganska tungt och då kan en extern variabel ibland vara en lösning.
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av johano »

Icecap skrev: Dock ska man ha klart för sig att det kan skapa problem att okritisk lägga variabler som används här, där och överallt. Det bästa är att separera funktioner så de innehåller de variabler de behöver och i grunden är "self-contained" och sedan kallar man med de variabler som behövs och de rätta svar returneras.

Men ibland kan det göra det hela ganska tungt och då kan en extern variabel ibland vara en lösning.
Exakt!! Jag skulle nog t.o.m. gå så långt som att säga "anropar man de funktioner som deklarerats. Att extern kod behöver tillgång till interna variabler är ett tecken på att designen är fel och att man snart har ett härke till projekt att underhålla ;-)

/j
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Tack så mycket :)
Ska följa era råd. Det blev faktiskt väldigt få variabler över som behövde vara extern efter att jag fått det att kompilera och städat lite i koden. Jag är lite stressad nu eftersom jag vill bli klar med båten tills jag åker till mina föräldrar nästa vecka.
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Hmmm...nu till ett litet annat problem. Jag tar in signalen via UART och ett "paket" ser ut såhär: [startbyte] [data1] [data2] .... [data22] [flags][endbyte]
Startbiten är alltid 11110000b (0xF0)
Slut-biten är alltid 00000000b (0x00)

Hur tusan synkar man detta emot UART? Jag har gjort som så nu att jag börjar läsa när det kommer en 0xF0 och läser då in 25 byte i en buffer. Sen kollar jag om inBuffer[0] är 0xF0 och inBuffer[24] är 0x00, om det stämmer läser jag ut buffern. Men problemet är ju att varken startbiten eller slutbiten är speciellt unik så det är inget säkert sätt att synka.
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Icecap »

Om det är en binär överföring där alla värden kan finnas fungerar det inte.

Då använder man en enda speciell byte som helst förekommer så lite som möjligt i datadelen och kallar den escape-char.

Start av paket blir då t.ex. escape - 0x01.
End av paket blir då t.ex. escape - 0x02.
För att skicka escape-char i datablocket skickar man t.ex. escape - 0x03.

I mottagningen silar man bort alla dubbel-char.

På detta vis får man unika kombinationer för start, stopp osv.
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Hmmm…jag har ännu inte fått det att fungera. Signalen kommer ifrån en Futaba RC-mottagare och SBUS-protokollet används på många saker så det måste gå att få till. Men jag misstänker att min baudrate inte riktigt stämmer. Det står att det ska vara 100kbps men jag hittade någon som skrev att det funkade ända ner till 97kbps och bäst på 98-99kbps.
Jag körde oscilloskopet på signalen samtidigt och kunde där se 25 bytes med rätt start- och stop-byte men AVR:en fick in 26 istället. Det var lätt att verifiera att stop-byten och byten innan den stämde överens med oscilloskopet...men alltså en byte mer någonstans däremellan.
Då tänkt jag att om baudrate är för hög så borde den ju läsa in för snabbt och alltså kunna få in en extra byte. Problemet är att jag har 16MHz på AVR:en och då gick ju 100kbps jämnt ut. Jag verkar hamna på 95MHz som närmast om jag går ett steg neråt och då funkar det inte.

Låter det rimligt och hur löser man det i så fall? Byter kristall?
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Jag kom på ett sätt att få det i synk med hjälp av en timer och en räknare. Räknaren ökar med 1 varje millisekund(och räknar till max 50), varje gång ett tecken tas emot på UART så nollställs räknaren. Sekvenserna med data sänds ca var 14:e millisekund. Om räknaren hunnit till längre än 8 när ett tecken kommer så är det början på sekvensen.
Det är inte klart men inget annat jag lyckats komma på har funkat bättre. Detta verkar mer pålitligt än att kolla vilka tecken som kommer, för det finns inga special-tecken för start och slut eftersom detta inte är en ASCII-sträng utan binära värden som kan vara vad som helst. Jag ska göra någon typ av begränsning på maxvärdet för bufferIndex men just nu ökade jag bara storleken på inBuffer till 30 eftersom "paketen" är max 26.

Kod: Markera allt

//Initiering
	UBRR1 = 19; //((16 000 000/800 000)-1)
	UCSR1A = (1<<U2X1);
	UCSR1B = (1<<RXEN1) | (1<<RXCIE1); //RX Enable, RX Interrupt Enable
	UCSR1C = (1<<UPM11) | (0<<UPM10) | (1<<USBS1); //Even parity, Two stop-bits

//Interrupt
ISR(USART1_RX_vect){
	inData = UDR1;
	if(Counter_ms > 8) bufferIndex = 0;
	inBuffer[bufferIndex++] = inData;
	Counter_ms = 0;
	return;
}
MEN...problemet med baudrate(eller om det kan vara något annat problem) kvarstår. När jag kontinuerligt skriver ut hela inBuffer på en display så är start-byten rätt hela tiden(0x0F) vilket känns okej eftersom koden inte kollar vilket tecken som kommer, den börjar bara om när räknaren gått över 8. Sen stämmer andra byten oftast men tredje byten och resten är lite konstig och när jag ändrar signalen(rör på spakarna till sändaren) så hoppar byte-sekvensens längd i mellan 25 och 26 bytes längd.
Det konstiga är att det finns Arduino-kod som läser Futaba SBUS via UART och då används baudrate 100kbps, vilket fungerar. Och även om 97-98kbps skulle vara korrekt så är 100kbps bara ca 2-3% fel och det borde väl egentligen funka ändå?

Detta är ett väldigt stort problem just nu och jag vet verkligen inte hur jag ska göra. Jag kan egentligen lika gärna ha gjort nått nybörjarfel som ställer till det. Att det ska vara två stop-bitar och Even parity står här: https://os.mbed.com/users/Digixx/notebo ... d-by-mbed/ Det är även den inställningen som gör att mitt oscilloskop visar rätt utan error.
Signalen är även inverterad men det har jag gjort med en transistor och oscilloskopet visar en snygg inverterad signal med skarpa flanker.

Edit: Att posta här gör förvånansvärt ofta att man kommer på eller ser saker man missat. Tror knappt mina ögon men visst tusan ställer jag om till 5-bitas tecken-längd på rad 5. Inte konstigt att det blir mysko. Återkommer...
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av 4kTRB »

Jag har också upptäckt det. Även om du inte får några direkta svar så är det tydligen väldigt effektivt att skriva ned problemet.
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Ja det händer att jag skriver ett långt inlägg och under tiden inser felet och behöver då inte posta :)

Ändrade till 8-bitars längd och nu funkade det perfekt. Förmodligen skulle i princip alla mina andra försök fungerat också om detta varit rätt från början. Problemet var att denna rad:

Kod: Markera allt

    UCSR1C = (1<<UPM11) | (0<<UPM10) | (1<<USBS1); //Even parity, Two stop-bits
...nollställer de bitar som väljer tecken-längd som default är satta. Man kan ju köra |= för att inte ändra defult men jag körde alla bitar istället såhär:

Kod: Markera allt

UCSR1C = (0<<UMSEL11) | (0<<UMSEL10) | (1<<UPM11) | (0<<UPM10) | (1<<USBS1) | (1<<UCSZ11) | (1<<UCSZ10) | (0<<UCPOL1); //Even parity, Two stop-bits, 8-bit length
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Icecap »

Och sedan kommer jag och påstår att man ALDRIG ska lite på "default"!!!
Skriva ALLTID alla parameter i ett konfigurationsregister!

Så du hade faktisk gjort rätt till att börja med - men utelämnad vissa delar av värdet.
Glattnos
Inlägg: 2972
Blev medlem: 29 oktober 2009, 20:01:18

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av Glattnos »

Jag håller med helt, jag brukar definiera alla bitar när jag sätter register i initieringen, men nu var jag för brottom och gjorde ett nybörjarfel som kostade ca 6 timmars felsökning, det mest pinsamma är att man efter ca 2-3 timmar börja känna på sig att det är ett enkelt fel(eftersom inget verkar funka) men tänker fel för att komma på vad det är :oops:

En fråga till. Om man skriver såhär...

Kod: Markera allt

while(Sequence_timer < 300);
...och uppdaterar Sequence_timer i ett timer interrupt, triggar inte interrupt då? Jag har lagt while-loopen sist i initieringen precis före min huvud-loop("while(1)") där huvudprogrammet är för att jag behöver en liten fördröjning innan huvudprogrammet startar. Men det fastnar på den while-loopen.
ie
EF Sponsor
Inlägg: 1271
Blev medlem: 23 oktober 2006, 13:12:57
Ort: Tyresö

Re: Programeringsfrågor C++ radiostyrd båt

Inlägg av ie »

Du måste deklarera variabeln som volatile, så att kompilatorn inte tar dess värde för givet. (Dvs den kan ändras utan att kompilatorn vet om det (i Interuptet)).
Skriv svar