Steuerung mehrerer ESCs mit ATMEGA128 PWM

Ich habe also eine Weile an diesem Quadcopter gearbeitet und endlich alles gebaut und zusammengebaut. Der Versuch, einen Code zu schreiben, um den ESC zu steuern (RedBrick HobbyKing 30A mit UBEC). Ich habe es geschafft, einen ESC gemäß der Dokumentation zu aktivieren und ihn mit 50 Hz Fast PWM auf einem ATMEGA128 zu programmieren, der einen Motor steuert.

Das Problem, das ich jetzt habe, ist, dass, wenn ich versuche, mehrere Motoren zu verwenden, ich Probleme habe, sie alle richtig zu bewaffnen scheinen, es ist nur, wenn ich versuche, ihm Strom zu geben, es scheitert. Entweder beginnt ein Motor zu drehen, während der andere weiter piepst oder umgekehrt. Manchmal läuft keiner. Ich habe versucht, dieses Problem zu beheben, indem ich einen Interrupt verwende, der ausgelöst wird, wenn ICR1 erreicht wird (TCCR1A). Werfen Sie einen Blick auf den Code für weitere Details.

PS. Ich würde gerne die Logik hinter diesem Problem verstehen, warum es auftritt und was einige gängige Lösungen dafür sind. Denken Sie daran, dass ich neu in der AVR-Programmierung bin, daher wird eine allgemeine Terminologie bevorzugt. Danke!

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define ESC_LOW             1000    //low duty cycle in milliseconds
#define ESC_HIGH            2000    //high duty cycle in milliseconds
#define motors_ddr          DDRB    //the data direction register the motors will operate on
#define motors_port         PORTB   //the port the motors will operate on
#define north_motor         4       //pin number for this motor
#define south_motor         5       //pin number for this motor
#define east_motor          6       //pin number for this motor
#define west_motor          7       //pin number for this motor


void init_ESCs(void) {

    //set all motors pins to output
    //motors_ddr |= 1<<north_motor | 1<<south_motor | 1<<east_motor | 1<<west_motor;
    motors_ddr = 0xFF;
    /*
        Set the Waveform Generation Mode to Fast PWM
        Set WGM11, WGM12 & WGM13 to select Fast PWM
        Prescaler: 8 (set the CS11 bit)
        Set OCIE1A bit in TIMSK to enable the Output Compare Interrupt Enabled Register
    */
    TCCR1A |= 1<<WGM11;
    TCCR1B |= 1<<WGM13 | 1<<WGM12 | 1<<CS11;
    TIMSK |= 1<<OCIE1A;

    //my CPU is at 16MHz
    //Set the TOP i.e. Top = [ cpu_clk_speed Hz / (Prescaler) * (Frequency Hz) ] - 1
    ICR1 = 39999;

    //how many times to repeat the signal
    volatile int armCount = 170;
    volatile int confirmCount = 150;

    //this loop sends the 2ms signal
    while(armCount > 0) {

            if(TCNT1 >= ESC_HIGH && bit_is_set(motors_port, north_motor) && bit_is_set(motors_port, south_motor) && bit_is_set(motors_port, east_motor) && bit_is_set(motors_port, west_motor)) {
                armCount--;
                motors_port &= ~(1<<north_motor | 1<<south_motor | 1<<east_motor | 1<<west_motor);
                //motors_port &= 0b11110000; //set motor PINS LOW
            }
    }

    //wait a while before confirming the Arming process (dunno if this is necessary)
    _delay_ms(500);

    //this loop sends the 1ms signal completing the arming
    while(confirmCount > 0) {
        if(TCNT1 >= ESC_LOW && bit_is_set(motors_port, north_motor) && bit_is_set(motors_port, south_motor) && bit_is_set(motors_port, east_motor) && bit_is_set(motors_port, west_motor)) {

            confirmCount--;
            //motors_port &= 0b11110000; //set motor PINS LOW
            motors_port &= ~(1<<north_motor | 1<<south_motor | 1<<east_motor | 1<<west_motor);
        }
    }
}


void speed_test(int speed) {
    TCCR1A |= 1<<WGM11;
    TCCR1B |= 1<<WGM13 | 1<<WGM12 | 1<<CS11;
    TIMSK |= 1<<OCIE1A;

    ICR1 = 39999;

    while(1) {
        if(TCNT1 >= speed && bit_is_set(motors_port, north_motor) && bit_is_set(motors_port, south_motor) && bit_is_set(motors_port, east_motor) && bit_is_set(motors_port, west_motor)) {

            //motors_port &= 0b11110000; //set motor PINS LOW
            motors_port &= ~(1<<north_motor | 1<<south_motor | 1<<east_motor | 1<<west_motor);
        }
    }   
}

int main(void) {

    //set enabled interrupt bit
    sei();

    init_ESCs();

    //speed_test(1500); //1.5ms signal

    while(1) {

    }   
}

ISR (TIMER1_COMPA_vect) {
    //set all motor pins to HIGH
    motors_port |= 1<<north_motor | 1<<south_motor | 1<<east_motor | 1<<west_motor; 
}

Antworten (1)

Ich habe herausgefunden, was das Problem war. Ich habe 2 Fehler gemacht. Die erste war, keine geeignete Stromversorgung zu verwenden. Ein Motor würde gut funktionieren, aber sobald die anderen ansprangen, war einfach nicht genug Kraft da. Das zweite Problem war, dass ich Interrupts verwendete, obwohl ich die 4 PWM-Kanäle auf meinem atmega128 hätte nutzen sollen. Außerdem habe ich nicht ALLE 4 OCR-Kanäle aktiviert, ich habe vergessen, sie alle einzuschalten.

Wenn Sie also ähnliche Probleme haben, vergessen Sie nicht, eine geeignete Spannungsquelle zu verwenden, und stellen Sie sicher, dass Sie die PWM-Kanäle richtig einrichten und verwenden.

Selbstbeantwortete Fragen für einen Neuling sind immer nett :) Denken Sie daran, die Antwort zu akzeptieren.