Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2024:fstancu:ioan.birjovanu [2024/05/24 08:59]
ioan.birjovanu
pm:prj2024:fstancu:ioan.birjovanu [2024/05/27 11:50] (current)
ioan.birjovanu
Line 29: Line 29:
   * **Servomotorul:​** Un motor cu rotație fixă, unghiul de rotație al acestuia este controlat de microcontroller folosind un semnal PWM.   * **Servomotorul:​** Un motor cu rotație fixă, unghiul de rotație al acestuia este controlat de microcontroller folosind un semnal PWM.
   * **Controllerul brushless:​** Acesta controlează viteza de rotație a motorului brushless, primește valoarea PWM de la microcontroller.   * **Controllerul brushless:​** Acesta controlează viteza de rotație a motorului brushless, primește valoarea PWM de la microcontroller.
 +
 +<note tip>
 +Radiocomanda transmite receiverului 6 canale, dintre care noi folosim 4:
 +  * Canalul 1: Joystick-ul drept, axa Ox - folosit pentru a controla virajul robotului.
 +  * Canalul 2: Joystick-ul drept, axa Oy - folosit pentru a controla direcția de deplasare a robotului.
 +  * Canalul 3: Joystick-ul stâng, axa Oy - folosit pentru a controla viteza motorului brushless.
 +  * Canalul 5: Switch-ul A - folosit pentru a activa flamethrowerul.
 +</​note>​
 +
 +{{ pm:​prj2024:​fstancu:​flysky_schematic.jpg?​770 }}
 +
 +Astfel, acționând canalul 5 al teleccomenzii,​ robotul se va comporta în următorul fel:
 +
 +{{ pm:​prj2024:​fstancu:​robot_flame.jpg?​770 }}
  
 ===== Hardware Design ===== ===== Hardware Design =====
Line 204: Line 218:
  
 <note tip> <note tip>
-Descrierea codului aplicaţiei (firmware):​ +Codul de Arduino a rămas referința de bază pentru design-ul codului in AVR C pentru microcontrollerul AtMega328P
-  * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) +Acesta este codul pentru microcontroller scris în AVR C:
-  * librării şi surse 3rd-party (e.g. Procyon AVRlib) +
-  * algoritmi şi structuri pe care plănuiţi să le implementaţi +
-  * (etapa 3) surse şi funcţii implementate+
 </​note>​ </​note>​
  
-===== Rezultate Obţinute =====+<​code>​ 
 +#include <​avr/​io.h>​ 
 +#include <​avr/​interrupt.h>​ 
 +#include <​util/​delay.h>​
  
-<note tip> +#define CLOCK_SPEED 16000000UL 
-Care au fost rezultatele obţinute în urma realizării proiectului vostru. +#define BAUD 9600 
-</note>+#define MYUBRR CLOCK_SPEED/16/BAUD-1
  
-===== Concluzii =====+#define RCPinFWD PD2 
 +#define RCPinSide PD3 
 +#define RCPinSwitch PD4
  
-===== Download =====+#define Motor1Pin1 PB1 
 +#define Motor1Pin2 PB0 
 +#define Motor2Pin1 PB3 
 +#define Motor2Pin2 PB2 
 +#define RelayPin PB5 
 +#define ServoPin PB4
  
-<note warning> +volatile long StartTimeFWD = 0; 
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului:​ surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-).+volatile long CurrentTimeFWD = 0; 
 +volatile long PulsesFWD = 0; 
 +int PulseWidthFWD = 0;
  
-Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:​pm:​prj20??:​c?​** sau **:​pm:​prj20??:​c?:​nume_student** (dacă este cazul). **Exemplu:​** Dumitru Alin, 331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**. +volatile long StartTimeSide = 0; 
-</​note>​+volatile long CurrentTimeSide = 0; 
 +volatile long PulsesSide = 0; 
 +int PulseWidthSide = 0;
  
-===== Jurnal =====+int SwitchValue;​
  
 +void setup();
 +void loop();
 +void PulseTimerFWD();​
 +void PulseTimerSide();​
 +void init_timer1();​
 +void init_timer0();​
 +long pulseIn(uint8_t pin, uint8_t state);
 +long micros();
 +
 +volatile unsigned long timer0_overflow_count = 0;
 +
 +int main(void) {
 +    setup();
 +    while (1) {
 +        loop();
 +    }
 +}
 +
 +void setup() {
 +    // Set input and output pins
 +    DDRD &= ~((1 << RCPinFWD) | (1 << RCPinSide) | (1 << RCPinSwitch));​ // Set as input
 +    PORTD |= (1 << RCPinFWD) | (1 << RCPinSide); // Enable pull-up resistors
 +
 +    DDRB |= (1 << Motor1Pin1) | (1 << Motor1Pin2) | (1 << Motor2Pin1) | (1 << Motor2Pin2) | (1 << RelayPin) | (1 << ServoPin);
 +
 +    // Set up external interrupts for FWD and Side
 +    EICRA |= (1 << ISC00) | (1 << ISC10); // Any logical change on INT0 and INT1 generates an interrupt
 +    EIMSK |= (1 << INT0) | (1 << INT1); // Enable INT0 and INT1
 +
 +    init_timer1();​
 +    init_timer0();​
 +
 +    sei(); // Enable global interrupts
 +}
 +
 +void loop() {
 +    if (PulsesFWD < 2000) {
 +        PulseWidthFWD = PulsesFWD;
 +    }
 +    if (PulsesSide < 2000) {
 +        PulseWidthSide = PulsesSide;
 +    }
 +
 +    if (PulseWidthFWD > 1000 && PulseWidthSide > 1000) {
 +        if (PulseWidthFWD > 1550) {
 +            PORTB |= (1 << Motor1Pin1);​
 +            PORTB &= ~(1 << Motor1Pin2);​
 +        } else if (PulseWidthFWD < 1450) {
 +            PORTB &= ~(1 << Motor1Pin1);​
 +            PORTB |= (1 << Motor1Pin2);​
 +        } else {
 +            PORTB &= ~((1 << Motor1Pin1) | (1 << Motor1Pin2));​
 +        }
 +
 +        if (PulseWidthSide > 1550) {
 +            PORTB |= (1 << Motor2Pin1);​
 +            PORTB &= ~(1 << Motor2Pin2);​
 +        } else if (PulseWidthSide < 1450) {
 +            PORTB &= ~(1 << Motor2Pin1);​
 +            PORTB |= (1 << Motor2Pin2);​
 +        } else {
 +            PORTB &= ~((1 << Motor2Pin1) | (1 << Motor2Pin2));​
 +        }
 +    } else {
 +        PORTB &= ~((1 << Motor1Pin1) | (1 << Motor1Pin2) | (1 << Motor2Pin1) | (1 << Motor2Pin2));​
 +    }
 +
 +    SwitchValue = pulseIn(RCPinSwitch,​ HIGH);
 +
 +    OCR1A = SwitchValue;​ // Set PWM for servo
 +
 +    if (SwitchValue > 1000) {
 +        PORTB |= (1 << RelayPin);
 +    } else {
 +        PORTB &= ~(1 << RelayPin);
 +    }
 +}
 +
 +ISR(INT0_vect) {
 +    PulseTimerFWD();​
 +}
 +
 +ISR(INT1_vect) {
 +    PulseTimerSide();​
 +}
 +
 +void PulseTimerFWD() {
 +    CurrentTimeFWD = micros();
 +    if (CurrentTimeFWD > StartTimeFWD) {
 +        PulsesFWD = CurrentTimeFWD - StartTimeFWD;​
 +        StartTimeFWD = CurrentTimeFWD;​
 +    }
 +}
 +
 +void PulseTimerSide() {
 +    CurrentTimeSide = micros();
 +    if (CurrentTimeSide > StartTimeSide) {
 +        PulsesSide = CurrentTimeSide - StartTimeSide;​
 +        StartTimeSide = CurrentTimeSide;​
 +    }
 +}
 +
 +void init_timer1() {
 +    // Timer1 setup for servo control
 +    TCCR1A = (1 << WGM11) | (1 << COM1A1);
 +    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
 +    ICR1 = 39999; // 50Hz frequency
 +}
 +
 +void init_timer0() {
 +    // Timer0 setup for micros
 +    TCCR0A = 0;
 +    TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler 64
 +    TIMSK0 = (1 << TOIE0); // Enable overflow interrupt
 +}
 +
 +ISR(TIMER0_OVF_vect) {
 +    timer0_overflow_count++;​
 +}
 +
 +long micros() {
 +    unsigned long m;
 +    uint8_t oldSREG = SREG;
 +
 +    cli();
 +    m = timer0_overflow_count;​
 +    uint8_t t = TCNT0;
 +
 +    if ((TIFR0 & (1 << TOV0)) && (t < 255)) {
 +        m++;
 +    }
 +
 +    SREG = oldSREG;
 +    return ((m << 8) + t) * (64 / (F_CPU / 1000000L));
 +}
 +
 +long pulseIn(uint8_t pin, uint8_t state) {
 +    uint8_t bit = digitalPinToBitMask(pin);​
 +    uint8_t port = digitalPinToPort(pin);​
 +    uint8_t stateMask = (state ? bit : 0);
 +    unsigned long width = 0;
 +
 +    // Wait for any previous pulse to end
 +    while ((*portInputRegister(port) & bit) == stateMask);
 +
 +    // Wait for the pulse to start
 +    while ((*portInputRegister(port) & bit) != stateMask);
 +
 +    // Wait for the pulse to stop
 +    while ((*portInputRegister(port) & bit) == stateMask) {
 +        width++;
 +        if (width >= 1000000) {
 +            return 0;
 +        }
 +    }
 +
 +    return width;
 +}
 +</​code>​
 +
 +În codul de AVR, folosim hardware interrupts pe pinii de input pentru a identifica semnalele PWM de la receiverul radio, iar cu timerul 0 le măsurăm valoarea. Vom folosi apoi acele valori pentru a activa driverul de motoare DC pentru direcție, împreună cu servomotorul si controllerul de viteză pentru motorul brushless. Pentru a trimite un semnal PWM corespunzător valorii primite de la receiver la speed controller și servomotor, vom folosi timerul 1. 
 +
 +===== Concluzii =====
 +Acest proiect m-a ajutat să învăț despre programarea microprocesoarelor Atmel in AVR C, fără a folosi abstraction layer-ul oferit de Arduino IDE. De asemenea mi-a consolidat aptitudinile de CAD și de design de circuite.
 +
 +Abilitatea de a citi semnalele dintr-un receiver hobby-grade cu ajutorul unui microprocesor deschide o plajă largă de potențiale proiecte viitoare.
 +
 +===== Download =====
 <note tip> <note tip>
-Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului.+Link Repository Git: [[https://​github.com/​IonutBirjovanu/​AVR-BattleBot|BattleBot]]
 </​note>​ </​note>​
 +
 +<note tip>
 +Arhiva care conține următoarele fisiere:
 +  * 3D - un fisier cu toate piesele 3D folosite în proiectarea robotului.
 +  * Battlebot - implementarea proiectului în Arduino
 +  * media - conținut media cu robotul
 +  * Schematic photos - figurile schematicelor robotului
 +  * src - implementarea proiectului în AVR C
 +</​note>​
 +
 +{{pm:​prj2024:​fstancu:​proiect_pm_birjovanu_ioan.zip|arhiva}}
  
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
  
-<​note>​ +**Resurse Software** 
-Listă cu documente, datasheet-uri,​ resurse Internet folosite, eventual grupate pe **Resurse Software** ​şi **Resurse Hardware**. +  * [[https://​ocw.cs.pub.ro/​courses/​pm/​lab/​lab0-2023|Laboratorul 0: GPIO]] 
-</note>+  * [[https://​ocw.cs.pub.ro/​courses/​pm/​lab/​lab2-2023|Laboratorul 2: Întreruperi,​ Timere]] 
 +  * [[https://​ocw.cs.pub.ro/​courses/​pm/​lab/​lab3-2023-2024|Laboratorul 3: Timere, PWM]] 
 + 
 +**Resurse Hardware** 
 +  * [[https://​howtomechatronics.com/​|HowToMechatronics]] 
 +  * [[https://​electronoobs.com/|ElectroNoobs]]
  
 <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​ <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
  
pm/prj2024/fstancu/ioan.birjovanu.1716530361.txt.gz · Last modified: 2024/05/24 08:59 by ioan.birjovanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0