回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

程序设计篇 简单

头像 小怼怼 2021.01.07 742 0

在此小节中,你可以学到。如何安装Mind+软件以及连接要编程的目标设备和完成对TT扩展模块的出厂固件的烧录,在文章的最后给出了我们基于Mind+编写的第一个程序

project-image

在搜索引擎内搜索Mind+,注意网站的地址

project-image

大部分的读者还是Win下使用居多,有Mac的读者可以去官网学习Mac下的安装。这里限于篇幅就不展开讲解了

project-image

打开的首个页面,对于软件的具体使用,官网已经做了大量详尽的解释与说明

https://mindplus.dfrobot.com.cn/  ←----------------------------这个就是去官网的链接,一点既达

project-image

软件不算小,安装过后有1.5G这么大。注意自己C盘不够的,将软件放在D盘什么的。注意我说的话不是金科玉律,只是一种建议而已。

project-image

先点击我图中的位置,我们对TT模块进行出厂固件的重置

project-image

点第二个

project-image

固件是很复杂的代码,所以积木块没有给出。这边将代码放在了代码的手动编辑区。相关代码的作用可以参考我以往的内容。注意Arduino其实是用GCC(适合目标芯片)编译的,所以速度较慢。想要加快速度的,可以参考我以前写的文章,如何给Ardunio进行加速。当然有能力的建议在Liunx下编译,速度会快36%(指标,时间)

代码
/*
 * Copyright (C) 2020 DJI.
 *
 * SPDX-License-Identifier: BSD-3-Clause-Clear
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-08-25     robomaster   first version
 */

#include <Arduino.h>
#include <stdio.h>
#include <string.h>
#include <Wire.h>
#include "FS.h"
#include "SPIFFS.h"
#include <RMTT_Libs.h>
#include <RMTT_Shell.h>
#include <RMTT_Protocol.h>
#include <RMTT_GamesirT1d.h>

// #define __UART0_DEBUG__
// #define __DEFAULT_LOG__

#ifdef __UART0_DEBUG__
#define CommonSerial Serial
#else
#define CommonSerial Serial1
#endif

#define SDK_VERSION "esp32v1.0.0.11"

/* key doubleclick */
#define DOUBLECLICK_INTTERVAL_TIME 500

int led_callback(int argc, char *argv[], char argv2[]);
void led_task(void *pParam);

/* matrix */
#define MLED_BRIGHT   0xFF

int tof_range = 0;

int matrix_callback(int argc, char *argv[], char argv2[]);
int tof_callback(int argc, char *argv[], char argv2[]);
int version_callback(int argc, char *argv[], char argv2[]);
int rmtt_callback(int argc, char *argv[], char argv2[]);
int custom_callback(int argc, char *argv[], char argv2[]);

int unknown_cmd_callback(int argc, char *argv[], char argv2[]);

bool rmtt_int_is_valid();
bool rmtt_bool_is_valid();
bool rmtt_joystick_mac_is_valid();

int get_rmtt_int();
bool get_rmtt_bool();
uint8_t *get_rmtt_joystick_mac();

void matrix_show_graph_from_file();
int move_param_is_valid(char *argv, char *color);

RMTT_RGB tt_rgb;
RMTT_Matrix tt_matrix;
RMTT_GamesirT1d *p_tt_gamesir;
RMTT_TOF tt_tof;
RMTT_Protocol tt_sdk;

bool pair_mode = false;

TaskHandle_t gamesirPairingTaskHandle = NULL;
TaskHandle_t gamesirTaskHandle = NULL;
TaskHandle_t tofBatteryReadTaskHandle = NULL;
TaskHandle_t bleStatusTaskHandle = NULL;

void gamesir_pairing_task(void *arg);
void gamesir_task(void *arg);
void tof_battery_read_task(void *arg);
void ble_status_task(void *arg);
void wifi_upgrade();

// 16x8 heart figure.
static uint8_t tt_graph_buff[] = {
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0, 255, 255,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0, 255, 255, 255,   0, 255,   0, 255,   0, 255,   0, 255,   0,
      0,   0,   0,   0, 255, 255,   0,   0,   0,   0, 255,   0,   0,   0,   0,   0,
      0,   0,   0,   0, 255, 255,   0,   0,   0,   0, 255,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 255,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 255,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
};

int tof_callback(int argc, char *argv[], char argv2[])
{
    CommonSerial.printf("tof %d", tof_range);
}

void IRAM_ATTR key_doubleclick()
{
    static uint32_t last_press_time = 0, now_press_time = 0;
    static uint8_t key_toggle = 0;

    uint32_t interval;

    if (digitalRead(34) != 0)
    {
        return;
    }

    if (last_press_time == 0)
    {
        last_press_time = millis();
    }

    now_press_time = millis();

    interval = now_press_time - last_press_time;

    if ((interval > 50) && (interval < DOUBLECLICK_INTTERVAL_TIME))
    {
         if (!key_toggle)
        {
            CommonSerial.printf("[TELLO] motoron");
#ifdef __DEFAULT_LOG__
            Serial.printf("[TELLO] motoron");
#endif
        }
        else
        {
            CommonSerial.printf("[TELLO] motoroff");
#ifdef __DEFAULT_LOG__
            Serial.printf("[TELLO] motoroff");
#endif
        }
        key_toggle = !key_toggle;
    }
    last_press_time = now_press_time;
}

int i2c_init_failed = 0;

/**
 * Initialize the Matrix and show a TT Logo
 */
void setup_graph()
{
    if (!i2c_init_failed)
    {
        RMTT_Matrix::Init(127);
        RMTT_Matrix::SetLEDStatus(RMTT_MATRIX_CS, RMTT_MATRIX_SW,
                                  RMTT_MATRIX_LED_ON);
        // Set LED brightness for all LEDs from an array.
        RMTT_Matrix::SetAllPWM((uint8_t *)tt_graph_buff);
        delay(200);
        matrix_show_graph_from_file();
    }

}

void setup()
{
    pinMode(34, INPUT_PULLUP);
    if (digitalRead(34) == 0)
    {
        wifi_upgrade();
    }

    // put your setup code here, to run once:
    Serial.begin(115200);
    Wire.begin(27, 26);
    Wire.setClock(400000);
    Serial1.begin(1000000, 23, 18, SERIAL_8N1);
    Serial.println();

    // user key, 0:press, 1:up
    pinMode(34, INPUT_PULLUP);
    attachInterrupt(34, key_doubleclick, FALLING);

    Serial.println("*********RoboMaster Tello Talent********");
    Serial.println(SDK_VERSION);
    Serial.println();

    RMTT_RGB::Init();
    RMTT_RGB::SetRGB(255, 0, 0);
    delay(200);
    RMTT_RGB::SetRGB(0, 255, 0);
    delay(200);
    RMTT_RGB::SetRGB(0, 0, 255);
    delay(200);
    RMTT_RGB::SetRGB(0, 0, 0);

    p_tt_gamesir = RMTT_GamesirT1d::GetInstance();

    shell_cmd_init();

    tt_tof.SetTimeout(500);

    if (!tt_tof.Init())
    {
        i2c_init_failed = 1;
#ifdef __DEFAULT_LOG__
        Serial.println("Failed to detect and initialize sensor!");
#endif
    }
    else
    {
        // increase timing budget to 200 ms
        tt_tof.SetMeasurementTimingBudget(200000);
        tt_tof.StartContinuous();
        setup_graph();

        cmd_register((char*)"mled", matrix_callback);
        cmd_register((char*)"tof?", tof_callback);
        matrix_effect_init(MLED_BRIGHT);
        xTaskCreateUniversal(tof_battery_read_task, "tof_battery_read_task", 4096, NULL, 2, &tofBatteryReadTaskHandle, 1);
    }

    cmd_register((char*)"led", led_callback);
    cmd_register((char*)"version?", version_callback);
    cmd_register((char*)"ETT", rmtt_callback);
    cmd_register((char*)"DIY", custom_callback);

    cmd_unknown_handle_register(unknown_cmd_callback);

    led_effect_init();

#ifndef __UART0_DEBUG__
    /* large number represent high priority  */
    xTaskCreateUniversal(gamesir_pairing_task, "gamesir_pairing_task", 4096, NULL, 2, &gamesirPairingTaskHandle, 1);
    xTaskCreateUniversal(gamesir_task, "gamesir_task", 8192, NULL, 3, &gamesirTaskHandle, 0);
    xTaskCreateUniversal(ble_status_task, "ble_status_task", 4096, NULL, 2, &bleStatusTaskHandle, 0);
#endif

}

void loop()
{
    /* Serial receive process from drone */
    while (CommonSerial.available())
    {
        int ret = cmd_process(CommonSerial.read());
        if (ret != 0)
        {
            CommonSerial.printf("command error: %d\r\n", ret);
        }
    }

#ifndef __UART0_DEBUG__
    if (Serial.available())
    {
        int i = 0;
        char buff[20] = {0};

        while (Serial.available() && (i < 20))
        {
            buff[i++] = Serial.read();
        }
        buff[19] = '\0';

        if (!strcmp(buff, "esp32version?"))
        {
            Serial.printf(SDK_VERSION);
        }
        else if (!strcmp(buff, "wifiversion?"))
        {
            Serial1.printf("[TELLO] wifiversion?");
        }
        else if (!strcmp(buff, "wifiupgrade"))
        {
            int upgrade_cnt = 0;
            while (1)
            {
                if (Serial.available())
                {
                    Serial1.write(Serial.read());
                    RMTT_RGB::SetGreen(255);
                }
                if (Serial1.available())
                {
                    Serial.write(Serial1.read());
                    RMTT_RGB::SetRed(255);
                }
                if (upgrade_cnt > 1000)
                {
                    RMTT_RGB::SetGreen(0);
                    RMTT_RGB::SetRed(0);
                    upgrade_cnt = 0;
                }
                upgrade_cnt++;
            }
        }
    }
#endif
    /* -------!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-------  */
    /* DO NOT ADD ANY CODE HERE FOR NOT BLOCKING THE RECEIVE FROM THE SERIAL */
    /*     YOU CAN ADD YOUR USER CODE TO THE 'user_task' FUNCTION ABOVE      */
    /* -------!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-------- */
}

/**
 * unknown command
 *
 *  @param argc Control argument
 *  @param argv[] Value argument 1
 *  @param argv2[] Value argument2
 */
int unknown_cmd_callback(int argc, char *argv[], char argv2[])
{
    Serial.printf("unknown cmd %s\r\n", argv[0]);
}

/*******************Matrix control part**************************/

/**
 * Show the graph pre-settled in the file onto the Matrix
 */
void matrix_show_graph_from_file()
{
    SPIFFS.begin(true);

    if(SPIFFS.exists("/graph_enable.txt"))
    {
        int i = 0;
        uint8_t graph_buff[128];
        File file = SPIFFS.open("/matrix_graph.txt", FILE_READ);
        if (file)
        {
            while (file.available() && (i < 128))
            {
                graph_buff[i++] = (char)file.read();
            }
            matrix_effect_set_graph(graph_buff);
        }
        file.close();
    }
}

/**
 * Handling the commands about the Matrix
 *
 * @param argc Control argument
 * @param argv[] Value argument 1
 * @param argv2[] Value argument2
 */
int matrix_callback(int argc, char *argv[], char argv2[])
{
    static uint8_t buff[128] = {0};

    memset(buff, 0, 128);

    if ((!strcmp(argv[1], "g")) || (!strcmp(argv[1], "sg")))
    {
        if (argc == 3)
        {
            if (rbpstr2buff(buff, argv[2], MLED_BRIGHT) != 0)
            {
                goto end;
            }
        }
        else if ((argc == 2) && strlen(argv2))
        {
            if (rbpstr2buff(buff, argv2, MLED_BRIGHT) != 0)
            {
                goto end;
            }
        }
        else
        {
            goto end;
        }

        matrix_effect_set_graph(buff);

        if (!strcmp(argv[1], "sg"))
        {
            File file = SPIFFS.open("/matrix_graph.txt", FILE_WRITE);
            File file2 = SPIFFS.open("/graph_enable.txt", FILE_WRITE);
            if (file)
            {
                file.write(buff, sizeof(buff));
            }
            file.close();
            file2.close();
        }
    }
    else if ((!strcmp(argv[1], "sc")) && (argc == 2))
    {
        if(SPIFFS.exists("/graph_enable.txt"))
        {
            SPIFFS.remove("/graph_enable.txt");
        }
        matrix_effect_set_graph(buff);
    }
    else if ((!strcmp(argv[1], "s")) && (argc == 4) && (strlen(argv[2]) == 1))
    {
        if (strlen(argv[3]) == 1)
        {
            if (mled_font2buff(buff, argv[3][0], argv[2][0], MLED_BRIGHT) != 0)
            {
                goto end;
            }
        }
        else if (!strcmp(argv[3], "heart"))
        {
            if (mled_font2buff(buff, 0x104, argv[2][0], MLED_BRIGHT) != 0)
            {
                goto end;
            }
        }
        else
        {
            goto end;
        }

        matrix_effect_set_graph(buff);
    }
    else if ((!strcmp(argv[1], "sl")) && (argc == 3))
    {
        int gcc = 127;
        if (sscanf(argv[2], "%d", &gcc))
        {
            if ((gcc >= 0) && (gcc <= 255))
            {
                tt_matrix.SetGCC(gcc);
            }
            else
            {
                goto end;
            }
        }
        else
        {
            goto end;
        }
    }
    else if (!move_param_is_valid(argv[1], argv[2]))
    {
        float mv_t = 1;

        if (sscanf(argv[3], "%f", &mv_t))
        {
            /* mv_t 0.1~2.5 */
            if (!((mv_t >= 0.09) && (mv_t <= 2.51)))
            {
                goto end;
            }
        }
        else
        {
            goto end;
        }

        if (argc == 5)
        {
            if (argv[2][0] != 'g')
            {
                matrix_effect_move_str(argv[4], strlen(argv[4]), argv[2][0], argv[1][0], mv_t);
            }
            else
            {
                if (rbpstr2buff(buff, argv[4], MLED_BRIGHT) != 0)
                {
                    goto end;
                }
                matrix_effect_move_graph(buff, argv[1][0], mv_t);
            }

        }
        else if ((argc == 4) && strlen(argv2))
        {
            if (argv[2][0] != 'g')
            {
                matrix_effect_move_str(argv2, strlen(argv2), argv[2][0], argv[1][0], mv_t);
            }
            else
            {
                if (rbpstr2buff(buff, argv2, MLED_BRIGHT) != 0)
                {
                    goto end;
                }
                matrix_effect_move_graph(buff, argv[1][0], mv_t);
            }

        }
        /* 支持字符串中带有空格显示,单个单词要求小于40 */
        else if (argc >= 6)
        {
            if (argv[2][0] != 'g')
            {
                char str_tmp[256] = "";
                int len = 0;

                for (int i = 0; i < argc - 4; i++)
                {
                    if (len + strlen(argv[4+i]) + 1 < 256)
                    {
                        // Serial.printf("Before %s\n %d %s %d\r\n",str_tmp, len, argv[4 + i], strlen(argv[4 + i]));
                        memcpy(str_tmp + len , argv[4 + i], strlen(argv[4 + i]));
                        if (i < argc - 3)
                        {
                            memcpy(str_tmp + len + strlen(argv[4+i]), " ", 1);
                            len += 1;
                        }
                        len += strlen(argv[4+i]);
                        // Serial.printf("After %s %d %s %d\r\n",str_tmp, len, argv[4 + i],strlen(argv[4 + i]));
                    }
                    else
                    {
                        break;
                    }
                }
                // Serial.printf("%s %d\r\n",str_tmp, len);
                matrix_effect_move_str((char *)str_tmp, len, argv[2][0], argv[1][0], mv_t);
            }
        }
        else
        {
            goto end;
        }
    }
    else
    {
        goto end;
    }
    CommonSerial.print("matrix ok");
    return 0;
end:
    CommonSerial.print("matrix error");
    return 0;
}

int move_param_is_valid(char *argv, char *color)
{
    if (!strcmp(argv, "l")) {}
    else if (!strcmp(argv, "r")) {}
    else if (!strcmp(argv, "u")) {}
    else if (!strcmp(argv, "d")) {}
    else
    {
        return -1;
    }

    if (!strcmp(color, "r")) {}
    else if (!strcmp(color, "b")) {}
    else if (!strcmp(color, "p")) {}
    else if (!strcmp(color, "g")) {}
    else
    {
        return -1;
    }

    return 0;
}

/*******************Drone control part*****************************/
int rmtt_int = 0;
bool rmtt_bool = false;

bool int_is_valid = false;
bool bool_is_valid = false;

bool mac_is_valid = false;
uint8_t rmtt_mac[6] = {0};

/**
 * Drone connection handling, measure the connection state by serial data
 * feedback from the drone
 *  - Update connection state by parsing data feeded back from inner serial1
 *
 *  @param argc Control argument
 *  @param argv[] Value argument 1
 *  @param argv2[] Value argument2
 */
int rmtt_callback(int argc, char *argv[], char argv2[])
{
    if (!strcmp(argv[1], "ok"))
    {
        bool_is_valid = true;
        rmtt_bool = true;
    }
    else if (!strcmp(argv[1], "error"))
    {
        bool_is_valid = true;
        rmtt_bool = false;
    }
    else if (!strncmp(argv[1], "wifiv", 5))
    {
        /* report wifi version to PC */
        Serial.printf(argv[1]);
    }
    else if (!strcmp(argv[1], "mac"))
    {
        if ((sscanf(argv[2], "%02x%02x%02x%02x%02x%02x",
                    &rmtt_mac[0], &rmtt_mac[1], &rmtt_mac[2],
                    &rmtt_mac[3], &rmtt_mac[4], &rmtt_mac[5]) == 6)
         &&(argc == 3))
        {
            mac_is_valid = true;
#ifdef __DEFAULT_LOG__
            Serial.println("rmtt_callback(): mac get ok");
#endif
        }
        else
        {
#ifdef __DEFAULT_LOG__
            Serial.println("rmtt_callback(): mac get error");
#endif
        }

    }
    else if (sscanf(argv[1], "%d", &rmtt_int) && (argc == 2))
    {
        int_is_valid = true;
    }
    return 0;
}

/**
 * Get MAC valid state of the joystick
 *
 * @return the valid state of the MAC
 */
bool rmtt_joystick_mac_is_valid()
{
    return mac_is_valid;
}

/**
 * Get MAC of the joystick
 *
 * @return MAC of the joystick
 */
uint8_t *get_rmtt_joystick_mac()
{
    mac_is_valid = false;
    return rmtt_mac;
}

/**
 * Get valid state of whether having an Int type data received
 * from the drone
 *
 * @return valid state
 */
bool rmtt_int_is_valid()
{
    return int_is_valid;
}

/**
 * Get valid state of whether having an Boolean type data received
 * from the drone
 *
 * @return valid state
 */
bool rmtt_bool_is_valid()
{
    return bool_is_valid;
}

/**
 * Get the already received Int type data
 *
 * @return Int data from the drone
 */
int get_rmtt_int()
{
    int_is_valid = false;
    return rmtt_int;
}

/**
 * Get the already received Boolean type data
 *
 * @return Boolean data from the drone
 */
bool get_rmtt_bool()
{
    bool_is_valid = false;
    return rmtt_bool;
}

int version_callback(int argc, char *argv[], char argv2[])
{
    CommonSerial.printf("version %s", SDK_VERSION);
}

/**
 * Led command handling, control the color of the LED by input commands
 *
 *  @param argc Control argument
 *  @param argv[] Value argument 1
 *  @param argv2[] Value argument2
 */
int led_callback(int argc, char *argv[], char argv2[])
{
    int r1,b1,g1,r2,b2,g2;
    if (!strcmp(argv[1], "bl"))
    {
        float blink_freq = 1;
        if ((argc == 9)
          &&sscanf(argv[2], "%f", &blink_freq)
          &&sscanf(argv[3], "%d", &r1)
          &&sscanf(argv[4], "%d", &g1)
          &&sscanf(argv[5], "%d", &b1)
          &&sscanf(argv[6], "%d", &r2)
          &&sscanf(argv[7], "%d", &g2)
          &&sscanf(argv[8], "%d", &b2))
        {
            if ((blink_freq >= 0.09) && (blink_freq <= 10.1))
            {
                led_effect_blink(r1, g1, b1, r2, g2, b2, blink_freq);
                CommonSerial.print("led ok");
            }
            else
            {
                goto end;
            }

        }
        else
        {
            goto end;
        }

    }
    else if (!strcmp(argv[1], "br"))
    {
        float breath_freq = 1;
        if ((argc == 6)
          &&sscanf(argv[2], "%f", &breath_freq)
          &&sscanf(argv[3], "%d", &r1)
          &&sscanf(argv[4], "%d", &g1)
          &&sscanf(argv[5], "%d", &b1))
        {
            if ((breath_freq >= 0.09) && (breath_freq <= 2.51))
            {
                led_effect_breath(r1, g1, b1, breath_freq);
                CommonSerial.print("led ok");
            }
            else
            {
                goto end;
            }
        }
        else
        {
            goto end;
        }
    }
    else if (argc == 4)
    {
        if (sscanf(argv[1], "%d", &r1)
          &&sscanf(argv[2], "%d", &g1)
          &&sscanf(argv[3], "%d", &b1))
        {
            led_effect_set_rgb(r1, g1, b1);
            CommonSerial.print("led ok");
        }
        else
        {
            goto end;
        }
    }
    else
    {
        goto end;
    }

    return 0;
end:
    CommonSerial.print("led error");
    return 0;
}

/**
 * ToF measuring command handling
 *
 * @param arg Parameter about task control
 */
void tof_battery_read_task(void *arg)
{
    int range_ori = 0;
    int range_cm = 0;
    int battery_cnt = 0;
    for (;;)
    {
        range_ori = tt_tof.ReadRangeContinuousMillimeters();

        if (range_ori != 65535)
        {
            tof_range = range_ori;
        }

        if (!(battery_cnt % 10))
        {
            tt_sdk.ReadBattery();
        }

        if (tof_range >= 40 && tof_range <= 800)
        {
            range_cm = tof_range / 200.0;
            for (int i = 0; i < 8; i += 2)
            {
                if (2 * range_cm > i)
                {
                    tt_graph_buff[16 * 7 + i] = 0;
                    tt_graph_buff[16 * 7 + i + 1] = 255;
                }
                else
                {
                    tt_graph_buff[16 * 7 + i] = 0;
                    tt_graph_buff[16 * 7 + i + 1] = 0;
                }
            }
        }
        else if (tof_range > 800)
        {
            for (int i = 0; i < 8; i += 2)
            {
                tt_graph_buff[16 * 7 + i] = 0;
                tt_graph_buff[16 * 7 + i + 1] = 255;
            }
        }
        else
        {
            for (int i = 0; i < 8; i += 2)
            {
                tt_graph_buff[16 * 7 + i] = 0;
                tt_graph_buff[16 * 7 + i + 1] = 0;
            }
        }

        if (rmtt_int_is_valid())
        {
            int now_battery = get_rmtt_int();
            int val = now_battery / 25.0;

            for (int i = 8; i < 16; i += 2)
            {
                if (2 * val > i - 8)
                {
                    tt_graph_buff[16 * 7 + i] = 255;
                    tt_graph_buff[16 * 7 + i + 1] = 255;
                }
                else
                {
                    tt_graph_buff[16 * 7 + i] = 0;
                    tt_graph_buff[16 * 7 + i + 1] = 0;
                }
            }

            if ((now_battery >= 10) && (val == 0))
            {
                tt_graph_buff[16 * 7 + 8] = 80;
                tt_graph_buff[16 * 7 + 8 + 1] = 25;
            }

        }

        if (get_matrix_effect_mode() == MATRIX_EFFECT_FACTORY_MODE)
        {
            RMTT_Matrix::SetAllPWM((uint8_t *)tt_graph_buff);
        }
        battery_cnt++;
        delay(100);
    }
}

/**
 * Gamesir joystick pairing process handling
 *  - Detect the press event of the pairing button
 *  - Pair the joystick with the TT Plugin Module
 *
 * @param arg Parameter about task control
 */
void gamesir_pairing_task(void *arg)
{
    int __key_cnt = 0;
    for (;;)
    {
        if (digitalRead(34) == 0)
        {
            __key_cnt++;
        }
        else
        {
            __key_cnt = 0;
        }

        if (__key_cnt >= 20)
        {
            if (!p_tt_gamesir->GetConnectedStatus())
            {
                pair_mode = true;
                p_tt_gamesir->SetMACFilterEnable(false);
            }
        }

        delay(100);
    }
}

#define TAKEOFF_TIMEOUT 200

int takeoff_status = 0;

int now_time  = 0;
int last_clean_time  = 0;

/**
 * Gamesir joystick control handling
 *  - Receive command from the joystick
 *  - Control the drone by received command
 *
 * @param arg Parameter about task control
 */
void gamesir_task(void *arg)
{
    uint8_t command_init = 0;
    uint8_t mac_init = 0;

    uint8_t stop_cnt = 5;

    for (;;)
    {
        if (mac_init == 0)
        {
            CommonSerial.print("[TELLO] getmac?");
            delay(100);
#ifdef __DEFAULT_LOG__
            Serial.println("gamesir_task(): mac is ok?");
#endif
            if (rmtt_joystick_mac_is_valid())
            {
#ifdef __DEFAULT_LOG__
                Serial.println("gamesir_task(): ble mac init");
#endif
                p_tt_gamesir->Init(get_rmtt_joystick_mac());
                mac_init = 1;
            }
        }
        else if ((command_init == 0) && (p_tt_gamesir->GetConnectedStatus()))
        {
            tt_sdk.SDKOn();
            delay(100);
            if (rmtt_bool_is_valid())
            {
                command_init = 1;
            }
        }
        else if (p_tt_gamesir->DataIsValid())
        {
            // Serial.println("data is update");
            PlainData data = p_tt_gamesir->GetData();

            int lx = ((float)data.left_x_3d - 512) / 512.0 * 100;
            int ly = ((float)data.left_y_3d - 512) / 512.0 * 100;
            int rx = ((float)data.right_x_3d - 512) / 512.0 * 100;
            int ry = ((float)data.right_y_3d - 512) / 512.0 * 100;

            if ((data.btn3 == 0x01) && (data.L2))
            {
                tt_sdk.Flip('f');
            }
            else if ((data.btn3 == 0x03) && (data.L2))
            {
                tt_sdk.Flip('r');
            }
            else if ((data.btn3 == 0x05) && (data.L2))
            {
                tt_sdk.Flip('b');
            }
            else if ((data.btn3 == 0x07) && (data.L2))
            {
                tt_sdk.Flip('l');
            }
            else if ((data.Y) && (data.R2))
            {
                if (takeoff_status == 0)
                {
                    tt_sdk.TakeOff();
                    takeoff_status = 1;
                }
                else
                {
                    tt_sdk.Land();
                    takeoff_status = 0;
                }
            }
            else
            {
#ifdef BLE_JAPAN_CTRL
                tt_sdk.SetRC(lx, -ly, -ry, rx);
#else
                tt_sdk.SetRC(rx, -ry, -ly, lx);
#endif
            }
        }

        /* 避免rc指令粘包 */
        delay(10);

        /* Regularly send data packet to ensure the drone
        floating steadily after the controller was offline*/
        if ((now_time - last_clean_time > 300) && command_init)
        {
            if (p_tt_gamesir->GetDataOffline())
            {
                if (stop_cnt)
                {
                    tt_sdk.SetRC(0, 0, 0, 0);
                    stop_cnt--;
                }
            }
            else
            {
                /* keepactive */
                CommonSerial.print("[TELLO] keepalive");
                stop_cnt = 5;
            }
            last_clean_time = millis();
        }
        else
        {

        }

        now_time = millis();
    }
}

/**
 * Gamesir joystick Bluetooth(BLE) connection handling
 *
 * @param arg Parameter about task control
 */
void ble_status_task(void *arg)
{
    static int __led_cnt = 0;
    static uint8_t toggle = 0;
    uint8_t ble_mac[6] = {0};

    while (1)
    {
        if (get_led_effect_mode() == LED_EFFECT_FACTORY_MODE)
        {
            if (p_tt_gamesir->GetConnectedStatus())
            {
                if (pair_mode == true)
                {
                    memcpy(ble_mac, p_tt_gamesir->GetMAC(), 6);
                    p_tt_gamesir->SetMACFilterEnable(true);
                    CommonSerial.printf("[TELLO] setmac %02x%02x%02x%02x%02x%02x",
                                        ble_mac[0], ble_mac[1], ble_mac[2],
                                        ble_mac[3], ble_mac[4], ble_mac[5]);
                    delay(50);
                    if (rmtt_bool_is_valid())
                    {
#ifdef __DEFAULT_LOG__
                        Serial.println("ble_status_task(): peer is successful");
#endif
                        if (get_rmtt_bool())
                        {
                            pair_mode = false;
                        }
                    }
                }
                RMTT_RGB::SetBlue(255);
            }
            else if (pair_mode == true)
            {
                if (__led_cnt % 4 == 0)
                {
                    toggle = ~toggle;
                }

                if (!toggle)
                {
                    RMTT_RGB::SetBlue(0);
                }
                else
                {
                    RMTT_RGB::SetBlue(255);
                }
            }
            else
            {
                RMTT_RGB::SetBlue(0);
            }
        }

        __led_cnt++;
        delay(100);
    }
}

void wifi_upgrade()
{
    int cnt = 0;
    // put your setup code here, to run once:
    Serial.begin(921600);
    Serial1.begin(1000000, 23, 18, SERIAL_8N1);
    RMTT_RGB::Init();
    RMTT_RGB::SetRGB(0, 255, 0);
    delay(500);
    while (1)
    {
        if (Serial.available())
        {
            Serial1.write(Serial.read());
            RMTT_RGB::SetGreen(255);
        }
        if (Serial1.available())
        {
            Serial.write(Serial1.read());
            RMTT_RGB::SetRed(255);
        }
        if (cnt > 1000)
        {
            RMTT_RGB::SetGreen(0);
            RMTT_RGB::SetRed(0);
            cnt = 0;
        }
        cnt++;
    }
}


/**
 * DIY command callback
 *
 *  @param argc Control argument
 *  @param argv[] Value argument 1
 *  @param argv2[] Value argument2
 */
int custom_callback(int argc, char *argv[], char argv2[])
{
    // you can do what you want after receive diy command.
}


project-image

点击串口进行连接目标设备

project-image

扩展积木选择,TT

 

project-image

如果没有什么差错,你应该是可以看到这个上传页面的

project-image

这个是我们烧录的页面,在完成以上的连接以后。我们将出厂默认的程序烧录在扩展模块内

project-image

TT与飞机相连,接管了TT飞机内的无线通信链路。所有指令都是先由扩展件转发给TT。

project-image

俗话说,一图胜千言。上一图就可以说明TT与扩展件之间的关系了

project-image
代码
/*!
 * MindPlus
 * telloesp32
 *
 * 等待扩展模块上的绿灯亮起后,按下按钮,绿灯熄灭后,飞机起桨1s,随后起飞。当检测到挑战卡后,扩展模块亮相应颜色的灯,并飞往最快识别到的挑战卡的(100,0,80)坐标,在飞行路线上,若检测到了另外一张挑战卡,则停止飞行,并在这张挑战卡上偏航90度,随后降落。
 */
#include <Wire.h>
#include <RMTT_Libs.h>
// 静态常量
const uint8_t bitmap[][128] = {
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,255,0,255,0,0,0,0,0,255,0,255,0,255,0,255,0,255,0,255,0,0,0,0,0,255,0,255,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0},
	{0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,255,0,255,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,255,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,255,0,255,0,255,0,255,255,255,255,255,255,255,255,255,0,255,255,255,255,255,0,255,255,255,255,255,255,255,255,255,0,255,255,255,255,255,0,255,255,255,255,255,255,255,255,255,0,255,255,255,255,255,0,255,255,255,255,255,255,255,0,255,0,255,255,255,0,255,0,255,255,255,255,255,255,255,0,255,0,255,255,255,0,255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,0,252,0,252,0,252,0,0,0,0,0,0,0,0,0,252,0,0,0,0,0,252,0,0,0,0,0,0,0,0,0,252,0,0,0,0,0,252,0,0,0,0,0,0,0,0,0,252,0,0,0,0,0,252,0,0,0,0,0,0,0,252,0,252,0,0,0,252,0,252,0,0,0,0,0,0,0,252,0,252,0,0,0,252,0,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,255,244,255,0,0,0,0,244,255,244,255,0,0,0,0,244,255,244,255,0,0,0,0,244,255,244,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,255,0,0,0,0,244,255,0,0,0,0,0,0,0,0,0,0,244,255,244,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
// 创建对象
RMTT_Protocol protocol;
RMTT_RGB      tt_rgb;
RMTT_TOF      tt_sensor;
RMTT_Matrix   tt_matrix;


// 主程序开始
void setup() {
	Serial1.begin(1000000, 23, 18, SERIAL_8N1);
	tt_rgb.Init();
	Wire.begin(27, 26);
	tt_sensor.Init();
	tt_matrix.Init(127);
	tt_matrix.SetLEDStatus(RMTT_MATRIX_CS, RMTT_MATRIX_SW, RMTT_MATRIX_LED_ON);
	protocol.startUntilControl();
	protocol.sendTelloCtrlMsg("mon");
	protocol.sendTelloCtrlMsg("mdirection 2");
	protocol.sendTelloCtrlMsg("motoron");
	delay(1000);
	protocol.sendTelloCtrlMsg("motoroff");
	delay(1000);
	protocol.sendTelloCtrlMsg("takeoff");
	for (int index = 0; index < 10; index++) {
		if ((1==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(0,0,255);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[0]);
		}
		else if ((2==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(0,255,0);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[1]);
		}
		else if ((3==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(255,0,0);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[2]);
		}
		else if ((4==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(255,255,255);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[3]);
		}
		else if ((5==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(255,255,0);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[4]);
		}
		else if ((6==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(0,255,255);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[5]);
		}
		else if ((7==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(255,153,255);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[6]);
		}
		else if ((8==protocol.getTelloMsgInt("[TELLO] mid?", 1000))) {
			tt_rgb.SetRGB(0,0,0);
			tt_matrix.SetAllPWM ((uint8_t*)bitmap[7]);
		}
		protocol.sendTelloCtrlMsg((char *)String(String("jump ")+int(100)+" "+int(0)+" "+int(80)+" "+int(50)+" "+int(90)+" "+"m-1"+" "+"m-1").c_str());
	}
	protocol.sendTelloCtrlMsg("land");
}
void loop() {

}

有的读者可能不熟悉Mind+的积木化编程,我这边将原生的ino文件放了上来,感兴趣的可以直接去烧录。注意普通的Ardunio版本是无法对TT直接编程,感兴趣的可以看我之前的环境搭建文章

评论

user-avatar