Bezdrôtová komunikácia v pásme 433 MHz.
Zo stránky SensorWiki
Autori: | Vladislav Bača |
Marcel Galovič | |
Študijný odbor: | Aplikovaná mechatronika |
Ročník: | 2. Ing. (2014) |
Zadanie
Treba popísať teóriu okolo bezdrôtovej komunikácie v tomto pásme, spôsoby prenosu dát, princíp AM a CPCA moduácie, RSSI a pod. Ďalej treba vyskúšať možnosti komunikačných modulov Parallax TrX module a naprogramovať bezpečný prenos dát medzi dvoma procesorovými modulmi.
Literatúra:
- 433 MHz RF Transceiver - prehlaď (parallax.com)
- 433 MHz RF Transceiver - Datasheet (.pdf)
Literatúra:
- Zoznam použitej literatúry, vrátane katalógových údajov (datasheet), internetových odkazov a pod.
Analýza
V rámci projektu sme mali zadanú úlohu, ktorá mala byť riešená na vývojovej doske ACROB (ACROB dokumentácia), ktorá disponuje mikroprocesorom ATmega328P. Bezdrôtová komunikácia mala byť riešená pomocou komunikačných modulou Parallax 433 MHz RF Transceiver (Parallax 433MHz transceiver), ktorý komunikuje s mikroprocesorom pomocou periférie UART.
Schéma zapojenia vývodov RF modulu:
Našou snahou bolo vytvoriť jednoduchú aplikáciu s dostupným materiálom. Z tohto hľadiska sme sa rozhodli pre vytvorenie diaľkovo ovládaného jednoduchého 3 kolesového vozidla, ktoré bude poháňané dvomi Parallax Continuous Rotation Servo (Parallax Continuous Rotation Servo).
Pre riadenie tohto vozidla bol zvolený Joystick Dualshock 2 z hernej konzoly Playstation 2, ktorý obsahuje 2 analógové joysticky ktoré snímajú pohyb v 2 osiach. Princíp tohto mechanizmu je znázornený nižšie.
Schéma zapojenia analógového joysticku:
Popis riešenia
Celý projekt je možné rozdeliť na 2 časti, ktoré budú popísané postupne
- 1. Transmitter
- 2. Receiver
Transmitter
Vysielacia časť (Transmitter) je riadiacou časťou konštrukcie, ktorá vysiela riadiace signály pre prijímaciu časť (Receiver). Ako bolo vyššie spomenuté, základ tvorí vývojová doska ACROB, ktorá disponuje mikroprocesorom ATmega328P ktorý sníma pozíciu dvoch analógových joyistickov, na základe čoho je vysielaný reťazec znakov do RF modulu.
Snímanie pozície analógového joysticku je založené na snímaní analógového napätia v rozsahu 0 ÷ 5V (pri napájaní 5V), ktoré je snímané z bežca 10KOhm potenciometru umiestnenom v konštrukcii spomínaného joysticku. Pre každé z kolies je vyhradený jeden joystick. V pôvodnom stave je bežec nastavený na stred dráhy, čím je na výstupe napätie 2,5V. Tento signál je privedený na piny PC4 a PC5 na ktorých sa nachádza aj periféria analógovo digitálneho prevodníka so vstupmi ADC4 a ADC. Tieto analógové hodnoty sú procesorom spracované a prevedené na číslo, ktoré zodpovedá hodnote rýchlosti v %. Skutočnosť, že použitý typ serva je konštruovaný tak, aby sa mohol kontinuálne otáčať jedným, alebo druhým smerom, sme museli ošetriť rozdelením rozsahu na 2 polovice. Analógové napätie zodpovedajúce hodnote 0 ÷ 2,5 V je prepočítané na hodnotu 0-49% a napätie 2,5 ÷ 5V je prepočítané na hodnotu 49-99%. Pre komunikáciu s RF modulom je použitá sériová linka, ktorá komunikuje na prenosovej rýchlosti 9600 Bd. Pin RF modulu s názvom Serial Data bol pripojený k PD1 (TxD). Reťazec ktorý je posielaný z mikroprocesoru do RF modulu vyzerá nasledovne.
OBRÁZOK TOHO RETAZCA
Na začiatku vysielaného reťazca sa vysiela identifikátor, ktorý je konštantný a skladá sa zo znakov 5A*. Za ním nasleduje znak, ktorý rozhoduje o výbere pravého, resp. ľavého motora. Za ním nasleduje znak M (Motor) a znak S (speed). Za týmito znakmi sú vyslané 2 posledné znaky, ktoré reprezentujú percentuálne číslo rýchlosti. Tieto rámce sú vysielané s 10 ms odstupom, ktorý bol experimentálne zvolený.
Receiver
Prijímacia časť (Receiver) je riadenou časťou konštrukcie, ktorá vysielané dáta prijíma a spracováva. Je podobne ako vysielacia postavená na vývojovej doske ACROB s mikroprocesorom ATmega328P, ktorá je umiestnená na 3 kolesovom podvozku robota ACROB. Príjmanie dát zabezpečuje RF modul, ktorý je zapojený podľa obrázku nižšie. Dáta sú privedené na pin PD0 (RxD). Tieto dáta sú spracované a dekódované mikroprocesorom tak, aby bolo možné definovať, ktorý z motorov a akou rýchlosťou sa majú točiť. Tieto inštrukcie sú prevedené na šírku pulzu PWM signálu príslušného motoru, ktorý má byť riadený. Pri frekvencii 50Hz a šírke impulzu 1,5ms sa motor neotáča. Pre maximálnu rýchlosť otáčania v smere hodinových ručičiek je potrebná šírka 1,3ms a v protismere hodinových ručičiek je šírka impulzu 1,7ms pri tej istej frekvencii. Maximálne otáčky dosiahnuté pri napájacom napätí 5 V sú 50 min-1. Podrobné informácie o serve viď Parallax Continuous Rotation Servo Datasheet
Sem opíšete ako konkrétne ste problém vyriešili. Začnite popisom pripojenia k procesoru (nezabudnite na schému zapojenia!) a zdôraznite ktoré jeho periférie ste pritom využili.
Pozn.: Názov obrázku musí byť jedinečný, uvedomte si, že Obr1.jpg už pred vami skúsilo nahrať už aspoň 10 študentov.
Algoritmus a program: Transmitter
Uveďte stručný popis algoritmu, v akom jazyku a verzii vývojového prostredia ste ho vytvorili. Je vhodné nakresliť aspoň hrubú štruktúru programu napríklad vo forme vývojového diagramu. Rozsiahly program pre lepšiu prehľadnosť rozdeľte do viacerých súborov.
Vyberte podstatné časti zdrojového kódu, použite na to prostredie source:
#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdio.h>
#include "serial.h"
FILE uart_output = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE); //potrebný príkaz pre komunikáciu cez UART
FILE uart_input = FDEV_SETUP_STREAM(NULL, recchar, _FDEV_SETUP_READ); //potrebný príkaz pre komunikáciu cez UART
void posli_lavy(void); //definovanie funkcie na vysielanie znaku pre lavy motor
void posli_pravy(void); //definovanie funkcie na vysielanie znaku pre pravy motor
void delay_ms(int ms); //definovanie funkcie oneskorenia/cakania
unsigned int buffer; //vytvorenie premennej buffer, ktorá slúži pri dočasnom odkladaí hodnoty z ADC
float pomocna; //vytvorenie premennej pomocna
char jed_znak; //vytvorenie premennej jed_znak, ktorá obsahuje jednotkovú hodnotu vysielaného percentuálneho čísla
char des_znak; //vytvorenie premennej des_znak, ktorá obsahuje desiatkovú hodnotu vysielaného percentuálneho čísla
//****************************************************************************************************
//********************************* MAIN *******************************************************
//****************************************************************************************************
int main()
{
//Inicializacia seriovej linky
inituart();
stdout = &uart_output;
stdin = &uart_input;
while(1) //nekonečný cyklus
{
posli_lavy(); //Volanie funkcie na vysielanie reťazca pre lavý motor
posli_pravy(); //Volanie funkcie na vysielanie reťazca pre pravý motor
delay_ms(10); //čakacia slučka 10ms
}
}
//--------------------------------------------------------------------------------------------------------------------
//------------------------------------Funkcia na vyslanie udaju rychlosti laveho motora-------------------------------
//--------------------------------------------------------------------------------------------------------------------
void posli_lavy(void)
{
adc2_init(); //funkcia pre inicializáciu ADC pre kanál 5
ADCSRA |= (1<<ADSC); //Štart A/D prevodu
while ( !(ADCSRA & (1<<ADIF))); //čakanie, kým AD prevod nie je ukončený
buffer = ADC; //dočasné uloženie výsledku z AD prevodu
pomocna=buffer; //uloženie buffer do pomocnej
pomocna = (pomocna/1024)*100; //prepočet dat z ADC
des_znak=(pomocna/10)+48; //výpočet desiatok
jed_znak=(pomocna-(10*(des_znak-48)))+48; //výpočet jednotiek
delay_ms(10); //čakacia slučka 10ms
printf("5A*LMS%c%c",des_znak,jed_znak); //vyslanie dát po sériovej linke do RF modulu
}
//--------------------------------------------------------------------------------------------------------------------
//------------------------------------Funkcia na vyslanie udaju rychlosti praveho motora-------------------------------
//--------------------------------------------------------------------------------------------------------------------
void posli_pravy(void)
{
adc1_init(); //funkcia pre inicializáciu ADC pre kanál 4
ADCSRA |= (1<<ADSC); // Štart A/D prevodu
while ( !(ADCSRA & (1<<ADIF))); // čakanie, kým AD prevod nie je ukončený
buffer = ADC; //dočasné uloženie výsledku z AD prevodu
pomocna=buffer; //uloženie buffer do pomocnej
pomocna = (pomocna/1024)*100; //prepočet dat z ADC
des_znak=(pomocna/10)+48; //výpočet desiatok
jed_znak=(pomocna-(10*(des_znak-48)))+48; //výpočet jednotiek
delay_ms(10); //čakacia slučka 10ms
printf("5A*RMS%c%c",des_znak,jed_znak); //vyslanie dát po sériovej linke do RF modulu
}
//--------------------------------------------------------------------------------------------------------------------
//------------------------------------Inicializacia ADC4 vstupu-------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------
void adc1_init(void) // Inicializácia AD prevodu pre kanál 4
{
ADMUX = 0b01000100; // externá referencia, kanál 4 (ADC4) - NTC
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // =0b10000111, A/D zapnutý, delička = 128
}
//--------------------------------------------------------------------------------------------------------------------
//------------------------------------Inicializacia ADC5 vstupu-------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------
void adc2_init(void) // Inicializácia AD prevodu pre kanál 5
{
ADMUX = 0b01000101; // externá referencia, kanál 4 (ADC4) - NTC
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // =0b10000111, A/D zapnutý, delička = 128
}
//--------------------------------------------------------------------------------------------------------------------
//------------------------------------Funkcia oneskorenia/cakania-----------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------
void delay_ms(int ms)
{
unsigned int index;
while (ms)
{
index = 4*799;
while(index)
{
asm volatile ("nop");
index --;
}
ms--;
}
}
Zdrojový kód: Transmitter.c
Algoritmus a program: Receiver
#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdio.h>
#include "serial.h"
#define Pravy_ON PORTB |= 0x02; //Zapne Pravy motor
#define Pravy_OFF PORTB &= ~0x02; //Vypne Pravy motor
#define Lavy_ON PORTB |= 0x04; //Zapne Lavy motor
#define Lavy_OFF PORTB &= ~0x04; //Vypne Lavy motor
FILE uart_output = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE); //potrebný príkaz pre komunikáciu cez UART
FILE uart_input = FDEV_SETUP_STREAM(NULL, recchar, _FDEV_SETUP_READ); //potrebný príkaz pre komunikáciu cez UART
int input=0; //vytvorenie premennej input
unsigned char Prijate_data[8]; //vytvorenie pola znakov o veľkosti 8
unsigned int Speed_L=0; //vytvorenie premennej Speed_L (počiatočná hodnota = 0)
unsigned int Speed_R=0; //vytvorenie premennej Speed_R (počiatočná hodnota = 0)
void nastav_motorceky(int L,int R); //definovanie funkcie na nastavenie motorov so vstupnými hodontami L a R
void delay_ms(int ms); //definovanie funkcie oneskorenia/cakania
//*****************************************************************************************************************************
//************************************** MAIN ***************************************************************************
//*****************************************************************************************************************************
int main()
{
unsigned char i=0; //definovanie lokálnej premennej i
for(i=0;i<8;i++) // vynulovanie pola Prijate_data - sem sa budú ukladat prijate data z komunikacie a tie budu vyhodnocované
{
Prijate_data[i]=0;
}
//*****************************************************************************************************************************
//************************************* FORMAT pola Prijate_data: ****************************************************
//FORMAT pola Prijate_data:
//
// 5 A * L/R M S x x
// |___|___|___|___|___|___|___|___|
//
//Vysvetlivky: 5A* -> synchronizacia (kvoli problemom s pociatocnym prijatym znakom a rozpoznaním vysielaca )
// L/R -> výber laveho alebo praveho motora
// M -> motor (konstantny znak)
// S -> rýchlos (speed - konstantny znak)
// xx -> rychlost otacania motora v % (0-99)
//*****************************************************************************************************************************
//*****************************************************************************************************************************
//Inicializacia seriovej linky
inituart();
stdout = &uart_output;
stdin = &uart_input;
//Inicializacia PWM motorcekov
DDRB |= 0x06; //Nastavenie pinov PB1 a PB2
PORTB |= 0x01; //Nastavenie výstupu na log. 0
TCCR1A = 0b10100010; // Mód: PWM, Phase Correct, 9-bit
TCCR1B = 0b00011011; // Delička 1:1024
ICR1= 0x1388 ; // nastavenie 20ms = 50Hz
TCNT1 = 0x00;
while(1)
{
i=0;
do {
input = getchar(); //cakaj az kym nacita priate data z UART
Prijate_data[i]=input; //uloz prijate data do pola na poziciu i
i++; //inkrementuj premenu i o 1
}
while(input>='!' && input<='~' && i<8); //testuje sa na podmienku, či je prijaty znak znak z intervalu '!' az '~' a ci je pole uz uplne obsadene
//testovanie prijateho retazca
if(Prijate_data[3]=='L' && Prijate_data[4]=='M' && Prijate_data[5]=='S' && i==8) //Je splnená ak je 3. znak písmeno L a zároveň 4. znak písmeno M a zároveň je 5. znak písmeno S a zároveň je počet zankov 8
{
Speed_L=((Prijate_data[6]-48)*10)+(Prijate_data[7]-48); //potom premenná speed_L je vypočítaná zo 7. a 8. znaku poľa
}
if(Prijate_data[3]=='R' && Prijate_data[4]=='M' && Prijate_data[5]=='S' && i==8) //Je splnená ak je 3. znak písmeno R a zároveň 4. znak písmeno M a zároveň je 5. znak písmeno S a zároveň je počet zankov 8
{
Speed_R=((Prijate_data[6]-48)*10)+(Prijate_data[7]-48); //potom premenná speed_R je vypočítaná zo 7. a 8. znaku poľa
}
nastav_motorceky(Speed_L,Speed_R); //volanie funkcie na nastavenie rýchlosti motorov
}
}
//-----------------------------------------------------------------------------------------------------------------------------
//--------------------------------------Funkcia na nastavenie motorcekov-------------------------------------------------
void nastav_motorceky(int L,int R)
{
OCR1A=420-R-1; //nastavenie šírky impulzu pre pravý motor
OCR1B=321+L; //nastavenie šírky impulzu pre lavý motor
}
Zdrojový kód: Receiver.c
Overenie: Transmitter
Pre oživenie časti transmitter je potrebné pripojiť RF modul a analógový JOYSTICK k vývojovej doske ACROB tak ako to bolo zobrazené pri popise Transmittra. Otvorením súboru Transmitter.c v programe AVRstudio a správnym priradením knižníc by mal byť vygenerovaný .hex súbor bez komplikácií, ktorý je nahraný do mikroprocesora na doske ACROB. Po vykonaní týchto úkonov by malo byť na pine DATA RF modulu možné pomocou log. analyzátoru vidieť UART priebeh niekoľkých znakov nasledujúcich za sebou, ktorý má tvar popísaný v časti Receiver ( |5|A|*|L/R|M|S|x|x|). Teda 8 bajov celkovo za sebou nasledujúcich. Tieto priebehy by sa mali opakovať s odstupom každých 10 ms. Pri zmene polohy JOYSTICKu by sa mal meniť hodnota posledných 2 bajtov. Ak tomu tak nie je, je nutné skontrolovať, či sa mení napätie na výstupe z JOYSTICKu pri zmene polohy. Ďalej je nutné skontrolovať správnosť zapojenia a prípadné zlé kontakty na kontaktnom poli.
Ovládanie vysielača:
Ak sme namerali správne dáta na pine DATA RF modulu, jedinou potrebnou obsluhou je menenie polohy joysticku pre pravý/ľavý motor. Vzhľadom na skutočnosť, že sme využívali iba jednu os z každého joysticku, "páčky" reagujú iba na pohyb smerom dopredu/dozadu.
Overenie: Receiver
Pre oživenie časti transmitter je potrebné pripojiť RF modul a servá k vývojovej doske ACROB tak ako to bolo zobrazené pri popise Receivera. Otvorením súboru Transmitter.c v programe AVRstudio a správnym priradením knižníc by mal byť vygenerovaný .hex súbor bez komplikácií, ktorý je nahraný do mikroprocesora na doske ACROB. Po nahratí programu do mikroprocesoru je potrebné odpojiť programátor z dosky, pretože pri jeho ponechaní na doske nedokáže RF modul stiahnuť signál na pine RxD na úroveň log.0 čím je znemožnené mikroprocesoru vyhodnotiť prijaté dáta. Po vykonaní týchto krokov by malo všetko fungovať na prvý pokus. Ak sa vyskytne chyba, je možné opäť log. analyzátorom odsledovať dáta na pine DATA RF modulu. Mali by sa tam vyskytovať rovnaké dáta aké boli vysielané. V niektorých prípadoch sa výnimočne stane, že prvý bajt komunikácie je zmenený. To však program nijak neovplyvňuje, nakoľko je tento problém ošetrený. Pri pretrvávajúcom probléme je vhodné skontrolovať zapojenie a prípadné prerušenie kontaktu na kontaktnom poli. (Pozn: pre prácu so servami, ktoré sú pripojené ku konektoru X5 je potrebné, aby bol prepínač „power switch“ nachádajúci sa pod tlačidlom reset, v polohe 2)
Ovládanie prijímača:
Ak je všetko v poriadku a vyššie spomenuté kritéria sú splnené, obsluha tohto modulu nie je. O všetko riadenie sa stará modul vysielača.
Nezabudnite napísať čosi ako užívateľský návod. Z neho by malo byť jasné čo program robí, ako sa prejavuje a aké má užívateľské rozhranie (čo treba stlačiť, čo sa kde zobrazuje). Ak ste namerali nejaké signály, sem s nimi. Ak je výsledkom nejaký údaj na displeji, odfotografujte ho.
Fotogaléria
SEM DAME FOTKY Z USPESNEHO PROJEKTU :D
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.