DJI NAZA-M controller (remote controller side) see: https://developer.mbed.org/users/okini3939/notebook/drone/

Dependencies:   NECnfc SpiOLED USBHost mbed

main.cpp

Committer:
okini3939
Date:
2016-05-19
Revision:
1:d83f8332ebfe
Parent:
0:9f11e7a30865

File content as of revision 1:d83f8332ebfe:

#include "mbed.h"
#include "drone.h"
#include "SpiOLED.h"
#include "EthernetPowerControl.h"

#define STICK_CENTER 0x400
#define STICK_TILT   0x294
#define STICK_SWITCH 0x200
#define STICK_CHATTER 30

DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
DigitalOut led5(p26), led6(p29), led7(p30);
Serial pc(USBTX, USBRX);
AnalogIn adc[6] = {p20, p19, p18, p17, p16, p15};
DigitalIn sw[3] = {p23, p24, p25};
DigitalOut sw_pwr1(p21), sw_pwr2(p22);
SpiOLED oled(p5, p6, p7, p8, SpiOLED::LCD20x2);

volatile int received = 0;
struct AirData send_data;

struct Status stat, stat_gnd;
volatile int sw_fil = 0, sw_stat = 0, sw_cmd = 0, sw_xcmd = 0;
int mode = 0;
int rf_dual = 0;


void recvRf (struct GroundData *recv_data, int rssi) {

    if (recv_data->type != DATA_TYPE_GROUND) return;

    parseGps(recv_data->gps);
    parseCompass(recv_data->compass);
    stat.uptime    = recv_data->uptime;
    stat.battery   = recv_data->battery;
    stat.current   = recv_data->current;
    stat.amphour   = recv_data->amphour;
    stat.distance1 = recv_data->distance1;
    stat.distance2 = recv_data->distance2;

    received = recv_data->seq;
    led2 = !led2;

    log();
}

int getAnalog (int n) {
    int ad;

    __disable_irq();
    ad = (adc[n].read() - 0.5) * 2.0 * (STICK_TILT + STICK_CHATTER);
    __enable_irq();
    if (ad < - STICK_CHATTER) {
        ad += STICK_CHATTER;
    } else
    if (ad > STICK_CHATTER) {
        ad -= STICK_CHATTER;
    } else {
        ad = 0;
    }

    if (ad < - STICK_TILT) ad = - STICK_TILT;
    if (ad > STICK_TILT) ad = STICK_TILT;

    return STICK_CENTER + ad;
}

int getSwitch () {
    int i, r = 0;

    sw_pwr1 = 0;
    sw_pwr2 = 1;
    for (volatile int w = 0; w < 10; w ++);
    for (i = 0; i < 3; i ++) {
        if (!sw[i]) r |= (1<<(i * 2));
    }
    sw_pwr1 = 1;
    sw_pwr2 = 0;
    for (volatile int w = 0; w < 10; w ++);
    for (i = 0; i < 3; i ++) {
        if (!sw[i]) r |= (2<<(i * 2));
    }
    return r;
}

void input () {
    int a, b, c;

    a = getSwitch();
    if (a == sw_fil) {
        b = sw_stat;
        sw_stat = a;
        c = (b ^ a) & ~a;
        b = (b ^ a) & a;
        if (b) sw_cmd = b;
        if (c) sw_xcmd = c;
    }
    sw_fil = a;

    if (sw_stat & 0x01) {
        // start (ignition)
        send_data.aileron  = STICK_CENTER + STICK_TILT;
        send_data.elevator = STICK_CENTER + STICK_TILT;
        send_data.throttle = STICK_CENTER + STICK_TILT;
        send_data.rudder   = STICK_CENTER + STICK_TILT;
        led5 = 1;
    } else {
        // normal
        send_data.aileron  = getAnalog(0);
        send_data.elevator = getAnalog(1);
        send_data.throttle = getAnalog(2);
        send_data.rudder   = getAnalog(3);

        if (send_data.aileron == STICK_CENTER && send_data.elevator == STICK_CENTER && send_data.rudder == STICK_CENTER) {
            led6 = 1;
        } else {
            led6 = 0;
        }
        if (send_data.throttle == STICK_CENTER) {
            led7 = 1;
        } else {
            led7 = 0;
        }
    }

    send_data.analog1 = getAnalog(4);
    send_data.analog2 = getAnalog(5);
    send_data.sw1 = STICK_CENTER - (sw_stat & 0x04 ? STICK_SWITCH : 0) + (sw_stat & 0x08 ? STICK_SWITCH : 0);
    send_data.sw2 = STICK_CENTER - (sw_stat & 0x10 ? STICK_SWITCH : 0) + (sw_stat & 0x20 ? STICK_SWITCH : 0);
//    printf(" A=%03x, E=%03x, T=%03x, R=%03x, X1=%03x, X2=%03x, sw=%02x\r\n", send_data.aileron, send_data.elevator, send_data.throttle, send_data.rudder, send_data.analog1, send_data.analog2, sw);
}

void display () {
    if (sw_cmd & 0x02) {
        mode ++;
        sw_cmd = 0;
        oled.cls();
    }

    switch (mode) {
    case 0:
        oled.locate(0, 0);
        oled.printf("%4.1fV %4.1fA %4dmAh", (float)stat.battery / 1000.0, (float)stat.current / 1000.0, stat.amphour);
        oled.locate(0, 1);
        oled.printf("%4d %4d", stat.distance1, stat.distance2);
        break;
    case 1: // GPS
        oled.locate(0, 0);
        oled.printf("%8.5f %9.5f", (float)stat.gps_lat / 10000000.0, (float)stat.gps_lng / 10000000.0);
        oled.locate(0, 1);
        oled.printf("%4d %4d %4d %4d", stat.compass_x, stat.compass_y, stat.compass_z, stat.compass);
        break;
    case 2: // GPS
        oled.locate(0, 0);
        oled.printf("%4d %4d %4d %4d", stat.compass_x, stat.compass_y, stat.compass_z, stat.compass);
        oled.locate(0, 1);
        oled.printf("%4d %08d %06d", stat.gps_h, stat.gps_date, stat.gps_time);
        break;
    case 3: // GPS ground
        oled.locate(0, 0);
        oled.printf("%8.5f %9.5fG", (float)stat_gnd.gps_lat / 10000000.0, (float)stat_gnd.gps_lng / 10000000.0);
        oled.locate(0, 1);
        oled.printf("%4d %08d %06d", stat_gnd.gps_h, stat_gnd.gps_date, stat_gnd.gps_time);
        break;
    case 4: // stick
        oled.locate(0, 0);
        oled.printf("A%03x E%03x T%03x R%03x", send_data.aileron, send_data.elevator, send_data.throttle, send_data.rudder);
        oled.locate(0, 1);
        oled.printf(" %03x  %03x  %03x  %03x", send_data.analog1, send_data.analog2, send_data.sw1, send_data.sw2);
        break;
    default:
        mode = 0;
        break;
    }

    oled.locate(19, 0);
    oled.putc((received & 1) ? (rf_dual == 3 ? '*' : '.') : ' ');
/*
    pc.printf("Drone sec=%3d %4.1fV %4.1fA %4dmAh", stat.uptime, (float)stat.battery / 1000.0, (float)stat.current / 1000.0, stat.amphour / 1000);
    pc.printf("  dis1=%4d  dis2=%4d\r\n", stat.distance1, stat.distance2);
    pc.printf("  lat=%8.5f  lng=%9.5f", (float)stat.gps_lat / 10000000.0, (float)stat.gps_lng / 10000000.0);
    pc.printf("  h=%d  %08d  %06d\r\n", stat.gps_h, stat.gps_date, stat.gps_time);
    pc.printf("  x=%4d  y=4d  z=%4d  deg=%4d", stat.compass_x, stat.compass_y, stat.compass_z, stat.compass);
    pc.printf("  sat=%d  type=%d  flg=%d\r\n", stat.gps_sat, stat.gps_type, stat.gps_flg);
*/
}

void center () {
    int flg = 1;

    for (;;) {
        input();

        if (send_data.aileron == STICK_CENTER && send_data.elevator == STICK_CENTER && send_data.rudder == STICK_CENTER &&
          send_data.throttle == STICK_CENTER && send_data.analog1 == STICK_CENTER && send_data.analog2 == STICK_CENTER) {
            break;
        }

        if (flg) {
            flg = 0;
            oled.cls();
            oled.locate(6, 0);
            oled.printf("STICKS ARE");
            oled.locate(6, 1);
            oled.printf("NOT IN CENTER!");
        }

        oled.locate(0, 0);
        oled.printf("%4d", send_data.analog2 - STICK_CENTER);
        oled.locate(0, 1);
        oled.printf("%4d", send_data.analog1 - STICK_CENTER);
        led5 = !led5;
        wait_ms(200);
    }
    oled.cls();
}

void fault () {
    for (;;) {
        led5 = !led5;
        wait_ms(200);
    }
}

void adjust () {
    int i;

    if (stat_gnd.gps_date && stat_gnd.gps_time) {
        struct tm t;
        t.tm_year = ((stat_gnd.gps_date / 10000) % 10000) - 1900;
        t.tm_mon  = ((stat_gnd.gps_date / 100) % 100) - 1;
        t.tm_mday = (stat_gnd.gps_date % 100);
        t.tm_hour = (stat_gnd.gps_time / 10000) % 100;
        t.tm_min  = (stat_gnd.gps_time / 100) % 100;
        t.tm_sec  = stat_gnd.gps_time % 100;
        time_t gpstime = mktime(&t) + (9 * 60 * 60);

        time_t s = time(NULL);
        i = s > gpstime ? s - gpstime : gpstime - s;
        if (i > 1 && t.tm_sec >= 15 && t.tm_sec < 45 && t.tm_year >= 115 && t.tm_year < 138) {
            set_time(gpstime);
            printf("time adjust %d -> %d\r\n", s, gpstime);
        }
    }
}

int main() {
    int count = 0;
    Timer t;

    PHY_PowerDown();
//    Peripheral_PowerDown(LPC1768_PCONP_PCUSB|LPC1768_PCONP_PCENET|LPC1768_PCONP_PCI2S);
    Peripheral_PowerDown(LPC1768_PCONP_PCENET|LPC1768_PCONP_PCI2S);
    sw[0].mode(PullUp);
    sw[1].mode(PullUp);
    sw[2].mode(PullUp);
    memset(&stat, 0, sizeof(stat));
    pc.baud(115200);
    pc.printf("--- Drone Ground ---\r\n");

    center();
    oled.printf("Suga koubou - Drone");

    if (initRf()) {
        oled.cls();
        oled.printf("*** RF error!");
        fault();
    }
    initGps();

    wait_ms(500);
    adjust();
    initMsd();
    led1 = 1;

    t.start();
    for (;;) {
        pollRf();

        if (t.read_ms() >= (rf_dual == 3 ? 100 : 200)) {
            t.reset();

            // stick
            input();
            // send
            if (sendRf(&send_data)) {
                led4 = 1;
                led5 = 1;
            } else {
                led4 = 0;
            }
            led1 = !led1;

            if (received) {
                // oled
                display();
                led5 = 0;
                received = 0;
                count = 0;
            } else {
                count ++;
                if (count > 20) {
                    // lost
                    led5 = 1;
                }
                if (count % 2 == 0) {
                    display();
                }
                if (count % 10 == 0) {
                    log();
                }
            }

            // clock
            adjust();
        }

    }
}