查看“Cube小车/zh”的源代码
←
Cube小车/zh
跳转至:
导航
、
搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
{| style="width: 800px;" |- | ==概述== *项目名称:Microduino机器人小车 *目的:通过Microduino Joypad来控制BOXZ mini机器人小车 *难度:高级 *耗时:3小时 *制作者:Microduino Studio-YLB ==材料清单== *Microduino设备 {|class="wikitable" |- |模块||数量||功能 |- |[[Microduino-Core/zh]]||1||核心板(Joypad) |- |[[Microduino-Core+/zh]]||1||核心板(Robot) |- |[[Microduino-USBTTL/zh]]||1||下载程序 |- |[[Microduino-nRF24/zh]]||2||无线通讯 |- |[[Microduino-Joypad/zh]]||1||遥控 |- |[[Microduino-TFT/zh]]||1||显示 |- |[[Microduino-Motor/zh]]||1||四轴电机驱动 |- |[[Microduino-Robot/zh]]||1||驱动连接底板 |} *其他设备 {|class="wikitable" |- |模块||数量||功能 |- |机器小车机架||1||车体 |- |螺丝||18||固定 |- |螺母||8||固定 |- |Micro-USB数据线||1||下载程序 |- |车轮||1||车体 |- |电机||1||驱动车轮 |- |电池||1||供电 |} [[File:Boxz物料.jpg||600px|center|thumb]] ==实验原理== 机器人小车种类比较多,如循迹,壁障,蓝牙遥控小车,电脑鼠等。但是其行走控制方式基本是一样的,无非就是前后左右四个方向运动。当然结构上会有一定区别,不同功能需要采用不同传感器,本次我们主要使用两轮驱动,通过控制两个轮子的旋转方向,实现前进后退,旋转等功能,当然还要加上万向轮,这样才能保持平衡。 该小车结构简单,主要包括三个方面:车轮、车身、控制系统。 1)车轮采用两个减速电机,扭力大,可PWN调速,控制简单。 2)车身采用亚克力板,大小:8cm*8cm*8cm。 3)整个控制系统包括四个部分: *供电系统 因为BOXZ体积比较小,所以采用锂电池。 *中央处理器 中央处理器是整个小车的核心,就像电脑的CPU,人的大脑,有一定思维能力,能够处理复杂事件。采用Microduino-Core作为核心。 *无线通讯 小车采用Microduino-nRF24无线通讯方案,通讯速度响应快,控制范围:空阔地域大约100米。 *电机控制 采用Microduino-Motor直流电机驱动模块,一个模块能够驱动两个电机。同时结合Microduino-Robot底板,将中央处理器和直流电机模块连接起来。 ==文档== ==调试过程== 将Microduino Core、Microduino USBTTL堆叠在一起.用数据线将写好的程序通过Microduino USBTTL上传到Microduino Core上。 注意:最好不要将所有模块堆叠在一起之后再上传程序 [[File:download1.jpg||500px|center|thumb]] 打开Aroduino IDE,若电脑中没有安装,则参照附录中的安装方法,先安装Aicroduino IDE。点击左上【文件】选项→点击【打开】。 [[File:Bleopen.jpg||500px|center|thumb]] 浏览到项目程序地址,点击“Robot_v0.2.ino”程序打开 [[File:Boxzopen1.jpg||500px|center|thumb]] [[File:Boxzopen2.jpg||500px|center|thumb]] 之后点击左上角的"√"进行编译,点击上边栏的工具,确认板卡(Microduino-Core)处理器(Atmega328P@16M,5V)和端口号(COMX)。三项都如图确认无误之后点击"→"按钮下载程序到开发板上 [[File:Boxz步骤.jpg||500px|center|thumb]] Joypad操作说明 [[File:Joypadtest.jpg||300px|center|thumb]] [[File:Joypad物料.jpg||300px|center|thumb]] *左上边是油门控制开关,打开(拨到上面),才能进行控制,你可以摇动摇杆,观察屏幕的变化。 *右边开关是精度调整开关,开关拨到上面可以最大幅度控制,否则只能小幅度控制了,小幅度有助于稳定控制。 *左边摇杆本次未使用。 *右边摇杆在垂直方向上控制前后方向移动,往上向前,往下向后,在水平方向上控制左右方向移动。 Joypad开机设置 [[File:Joypadtest1.jpg||300px|center|thumb]] 打开遥控器电源开关,按下复位按键(左边USB接口右边那个)进入系统,请在4S内按下【key1】按键,进入遥控器校准和控制选择模式。 360度最大幅度旋转两个摇杆,遥控板会读入摇杆的位置数据,摇动至示数不再变化即可 [[File:Joypadtest2.jpg||300px|center|thumb]] 选择控制模式,可以通过【key3】按键来选择是控制四轴飞行器(Quad.)还是机器人(Robot),Robot模式可控制自平衡车和BOXZ mini,黑色表示选中。因此我们需要选择Robot模式。还可以通过【key4】按键来选择是否是体感控制模式,如果选择体感模式,你必须叠加Microduino-10DOF模块,选择“MPU ON”。如果是摇杆控制模式,选择“MPU OFF”。 这次搭建没有使用10DOF模块,因此选择MPU OFF模式; [[File:Joypadtest3.jpg||300px|center|thumb]] 选择完成后,通过【key2】按键退出配置,进入操作 [[File:Joypadtest4.jpg||300px|center|thumb]] 将左上边控制开关打开(拨到上面),才能进行控制,你可以摇动摇杆,观察屏幕的变化 [[File:Joypadtest5.jpg||300px|center|thumb]] 右边开关是幅度调节模式,开关拨到上面可以最大幅度控制Robot,否则只能小幅度控制。如果使用小幅度控制小车,右边摇杆拨到最大位置,小车速度也只能小范围变化,这样有助于稳定控制 [[File:Joypadtest6.jpg||300px|center|thumb]] 当启动小车时,只需要用到右边的摇杆,摇杆的方向和平衡车的方向一致,你可以尝试摇杆控制是否正确。如果发现方向有问题,可以在Robot_v0.2前4行代码更改引脚定义 如果原来的引脚定义如下: [[File:Boxzpin1.jpg||300px|center|thumb]] 而此时左右旋转反了,可以更改为 [[File:Boxzpin2.jpg||300px|center|thumb]] 如果最开始的引脚是情况2,那么方向错了就改成情况1就可以了。 打开BOXZ_mini小车上Microduino-Robot底板上的电源开关,拨到ON(左边),如果可以看到核心板上的红色led亮,说明供电正常。你可以愉快的玩耍了。 ==注意问题== *下载程序时候最好只叠加core(core+)和USBTTL,虽然本次搭建涉及的nRF24不会引起冲突,但是别的通信模块有时会造成串口冲突,养成好习惯。 *锂电池正负极别接错了,否则会烧坏电路。 *调试好后,实际运行时不要使用USB供电,电压不足,请使用电池。 ==小车程序说明== <source lang="cpp"> #define motor_pin0A 7 //PWM #define motor_pin0B 5 #define motor_pin1A 8 //PWM #define motor_pin1B 6 #define FIX_THROTTLE_A 1 //-1 or 1 #define FIX_THROTTLE_B -1 //-1 or 1 #define REVERSE_THROTTLE 1 //-1 or 1 #define REVERSE_STEERING 1 //-1 or 1 #define MAX_THROTTLE 255 //最大油门 100~255 #define MAX_STEERING 200 //最大转向 100~512 //rf======================================= #include <RF24Network.h> #include <RF24.h> #include <SPI.h> // nRF24L01(+) radio attached using Getting Started board RF24 radio(9, 10); RF24Network network(radio); const uint16_t this_node = 1; //设置本机ID const uint16_t other_node = 0; //-------------------------------- struct send_a //发送 { uint32_t node_ms; //节点运行时间 }; unsigned long last_sent = 0; //定时器 //-------------------------------- struct receive_a //接收 { uint32_t ms; uint16_t rf_CH0; uint16_t rf_CH1; uint16_t rf_CH2; uint16_t rf_CH3; uint16_t rf_CH4; uint16_t rf_CH5; uint16_t rf_CH6; uint16_t rf_CH7; }; unsigned long clock; //主机运行时间 int tem_xuan = 0; //主机请求时序 //---------------------------- boolean node_STA = false; float throttle; float steering; unsigned long safe_ms = millis(); void setup() { Serial.begin(115200); pinMode(motor_pin0A, OUTPUT); pinMode(motor_pin0B, OUTPUT); pinMode(motor_pin1A, OUTPUT); pinMode(motor_pin1B, OUTPUT); //nRF============================== SPI.begin(); //初始化SPI总线 radio.begin(); network.begin(/*channel*/ 70 , /*node address*/ this_node); Serial.println("===========start==========="); } int motor_vol[2]; // 主循环////////////////////////////////////////////////////////////////////////// void loop() { //=============================================================== if (nRF(&throttle, &steering)) { vorobot(); Serial.print(throttle); Serial.print(","); Serial.println(steering); } //=============================================================== if (safe_ms > millis()) safe_ms = millis(); if (millis() - safe_ms > 2000) { steering = 0; throttle = 0; digitalWrite(motor_pin0A, LOW); digitalWrite(motor_pin0B, LOW); digitalWrite(motor_pin1A, LOW); digitalWrite(motor_pin1B, LOW); } } void vorobot() { /* if(node_STA) { } */ //=============================================================== int motor_speed = 0; motor_speed = REVERSE_THROTTLE * throttle; motor_vol[0] = motor_speed; motor_vol[1] = motor_speed; //---------------------------------- int motor_steer = 0; motor_steer = REVERSE_STEERING * steering; motor_vol[0] -= motor_steer / 2; motor_vol[1] += motor_steer / 2; for (int a = 0; a < 2; a++) { if (motor_vol[a] > MAX_THROTTLE) { motor_vol[0] -= (motor_vol[a] - MAX_THROTTLE); motor_vol[1] -= (motor_vol[a] - MAX_THROTTLE); } else if (motor_vol[a] < -MAX_THROTTLE) { motor_vol[0] -= (MAX_THROTTLE + motor_vol[a]); motor_vol[1] -= (MAX_THROTTLE + motor_vol[a]); } } Serial.print(motor_vol[0]); Serial.print(","); Serial.print(motor_vol[1]); Serial.println(""); motor_vol[0] *= FIX_THROTTLE_A; motor_vol[1] *= FIX_THROTTLE_B; motor_driver(0, -motor_vol[0]); motor_driver(1, motor_vol[1]); } boolean motor_driver(int _motor_driver_num, int _motor_driver_vol) { switch (_motor_driver_num) { case 0: if (_motor_driver_vol == 0) { //Serial.println("0 OFF"); digitalWrite(motor_pin0A, LOW); digitalWrite(motor_pin0B, LOW); } else if (_motor_driver_vol > 0) { //Serial.println("0 Z"); analogWrite(motor_pin0A, _motor_driver_vol); digitalWrite(motor_pin0B, LOW); } else { //Serial.println("0 F"); analogWrite(motor_pin0A, 255 + _motor_driver_vol); digitalWrite(motor_pin0B, HIGH); } break; case 1: if (_motor_driver_vol == 0) { //Serial.println("1 OFF"); digitalWrite(motor_pin1A, LOW); digitalWrite(motor_pin1B, LOW); } else if (_motor_driver_vol > 0) { //Serial.println("1 Z"); analogWrite(motor_pin1A, _motor_driver_vol); digitalWrite(motor_pin1B, LOW); } else { //Serial.println("1 F"); analogWrite(motor_pin1A, 255 + _motor_driver_vol); digitalWrite(motor_pin1B, HIGH); } break; default : return false; } return true; } boolean nRF(float * _speed, float * _turn) { network.update(); // Is there anything ready for us? while ( network.available() ) { // If so, grab it and print it out RF24NetworkHeader header; receive_a rec; network.read(header, &rec, sizeof(rec)); clock = rec.ms; //接收主机运行时间赋值 float * _i = _speed; _i[0] = map(rec.rf_CH1, 1000, 2000, -MAX_THROTTLE, MAX_THROTTLE); _i = _turn; _i[0] = map(rec.rf_CH0, 1000, 2000, -MAX_STEERING, MAX_STEERING); node_STA = (rec.rf_CH7 > 1500 ? true : false); //接收请求时序赋值 { //Serial.print("Sending..."); send_a sen = { millis() }; //把这些数据发送出去,对应前面的发送数组 RF24NetworkHeader header(0); boolean ok = network.write(header, &sen, sizeof(sen)); safe_ms = millis(); if (ok) { return true; //Serial.println("ok."); } else { return false; //Serial.println("failed."); } } safe_ms = millis(); } } </source> ==程序说明== ==Joypad程序及说明== Joypad_RC.ino <source lang="cpp"> #include "Arduino.h" #include "def.h" #include "time.h" #include "bat.h" #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) #include "mpu.h" #endif #include "joy.h" #include "key.h" #include "data.h" #include "nrf.h" #include "mwc.h" #include "tft.h" #include "eep.h" #if defined(__AVR_ATmega128RFA1__) #include <ZigduinoRadio.h> #endif //joypad================================ #include <Joypad.h> //eeprom================================ #include <EEPROM.h> //TFT=================================== #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific #include <SPI.h> //rf==================================== #include <RF24Network.h> #include <RF24.h> #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) //MPU=================================== #include "Wire.h" #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #endif //spi=================================== #include <SPI.h> void setup() { // initialize serial communication at 115200 bits per second: #ifdef Serial_DEBUG Serial.begin(115200); delay(100); Serial.println("========hello========"); #endif //--------------- key_init(); //--------------- #ifdef Serial_DEBUG Serial.println("\n\r EEPROM READ..."); #endif eeprom_read(); //--------------- #ifdef Serial_DEBUG Serial.println("\n\r TFT INIT..."); #endif TFT_init(true, tft_rotation); //--------------- #ifdef Serial_DEBUG Serial.println("\n\r TFT BEGIN..."); #endif TIME1 = millis(); while (millis() - TIME1 < interval_TIME1) { TFT_begin(); if (!Joypad.readButton(CH_SWITCH_1)) { #ifdef Serial_DEBUG Serial.println("\n\rCorrect IN..."); #endif //--------------- #ifdef Serial_DEBUG Serial.println("\n\r TFT INIT..."); #endif TFT_init(false, tft_rotation); while (1) { if (!TFT_config()) break; } #ifdef Serial_DEBUG Serial.println("\n\rCorrect OUT..."); #endif //--------------- #ifdef Serial_DEBUG Serial.println("\n\r EEPROM WRITE..."); #endif eeprom_write(); } } //--------------- #ifdef Serial_DEBUG Serial.println("\n\r TFT CLEAR..."); #endif TFT_clear(); //--------------- #ifdef Serial_DEBUG Serial.println("\n\r TFT READY..."); #endif TFT_ready(); //---------------.l if (mode_protocol) //Robot { SPI.begin(); //初始化SPI总线 radio.begin(); network.begin(/*channel*/ nrf_channal, /*node address*/ this_node); } else //QuadCopter { unsigned long _channel; #if !defined(__AVR_ATmega128RFA1__) switch (mwc_channal) { case 0: _channel = 9600; break; case 1: _channel = 19200; break; case 2: _channel = 38400; break; case 3: _channel = 57600; break; case 4: _channel = 115200; break; } #else if _channel = mwc_channal; #endif mwc_port.begin(_channel); } //--------------- #ifdef Serial_DEBUG Serial.println("===========start==========="); #endif #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) if (mode_mpu) initMPU(); //initialize device #endif } void loop() { // unsigned long time = millis(); #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) //MPU-------------------------------- if (mode_mpu) getMPU(); #endif //DATA_begin------------------------------ data_begin(); //DATA_send------------------------------- if (millis() < time2) time2 = millis(); if (millis() - time2 > interval_time2) { if (mode_protocol) nrf_send(); //Robot else data_send(); //QuadCopter time2 = millis(); } //节点查错------------------------------- vodebug(); //BAT-------------------------------- if (time3 > millis()) time3 = millis(); if (millis() - time3 > interval_time3) { vobat(); time3 = millis(); } //TFT------------------------------------ TFT_run(); //=================================== // time = millis() - time; // Serial.println(time, DEC); //loop time } </cpp> BAT.h <source lang="cpp"> int8_t _V_bat = _V_min; boolean mcu_voltage = true; // 5.0 or 3.3 #define _V_fix 0.2 //fix battery voltage #define _V_math(Y) (_V_fix+((Y*analogRead(PIN_bat)/1023.0f)/(33.0f/(51.0f+33.0f)))) void vobat() { //_V_bat=10*((voltage*analogRead(PIN_bat)/1023.0f)/(33.0f/(51.0f+33.0f))); _V_bat = _V_math(mcu_voltage ? 50 : 33); _V_bat = constrain(_V_bat, _V_min, _V_max); #ifdef Serial_DEBUG Serial.print("_V_bat: "); Serial.println(_V_bat); #endif } </source> data.h <source lang="cpp"> #include "Arduino.h" byte inBuf[16]; int16_t outBuf[8] = { Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID }; boolean AUX[4] = {0, 0, 0, 0}; //====================================== void data_begin() { Joy(); if (mode_protocol) //Robot { if (!sw_l) { Joy_x = Joy_MID; Joy_y = Joy_MID; Joy1_x = Joy_MID; Joy1_y = Joy_MID; } } else //QuadCopter { if (!sw_l) Joy_y = Joy_MID - Joy_maximum; } //but--------------------------------- for (uint8_t a = 0; a < 4; a++) { if (key_get(a, 1)) AUX[a] = !AUX[a]; } outBuf[0] = Joy1_x; outBuf[1] = Joy1_y; outBuf[2] = Joy_x; outBuf[3] = Joy_y; outBuf[4] = map(AUX[0], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); outBuf[5] = map(AUX[1], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); outBuf[6] = map(AUX[2], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); outBuf[7] = map(AUX[3], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); } </source> def.h <source lang="cpp"> #include "Arduino.h" //DEBUG----------- #define Serial_DEBUG //MWC------------- uint8_t mwc_channal = 11; //RF channel #if defined(__AVR_ATmega32U4__) #define mwc_port Serial1 //Serial1 is D0 D1 #elif defined(__AVR_ATmega128RFA1__) #define mwc_port ZigduinoRadio //RF #else #define mwc_port Serial //Serial is D0 D1 #endif //nRF------------- #define interval_debug 2000 //节点查错间隔 uint8_t nrf_channal = 70; //0~125 //Battery--------- #define PIN_bat A7 //BAT #define _V_max 41 //锂电池满电电压4.2V #define _V_min 36 //锂电池没电电压3.7V #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) //MPU------------- #define MPU_maximum 70 #endif //Time------------ #define interval_TIME1 2000 //setup delay #define interval_time2 40 //send interval #define interval_time3 1000 //battery interval </source> eep.h <source lang="cpp"> #include "Arduino.h" #include <EEPROM.h> #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);} #define EEPROM_read(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);} struct config_type { int16_t eeprom_correct_min[4]; int16_t eeprom_correct_max[4]; uint8_t eeprom_Joy_deadzone_val; #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) boolean eeprom_mode_mpu; #endif boolean eeprom_mode_protocol; uint8_t eeprom_mwc_channal; uint8_t eeprom_nrf_channal; boolean eeprom_tft_theme; boolean eeprom_tft_rotation; boolean eeprom_mcu_voltage; }; //====================================== void eeprom_read() { //EEPROM读取赋值 config_type config_readback; EEPROM_read(0, config_readback); for (uint8_t a = 0; a < 4; a++) { joy_correct_min[a] = config_readback.eeprom_correct_min[a]; joy_correct_max[a] = config_readback.eeprom_correct_max[a]; } Joy_deadzone_val = config_readback.eeprom_Joy_deadzone_val; mode_protocol = config_readback.eeprom_mode_protocol; #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) mode_mpu = config_readback.eeprom_mode_mpu; #endif mwc_channal = config_readback.eeprom_mwc_channal; nrf_channal = config_readback.eeprom_nrf_channal; tft_theme = config_readback.eeprom_tft_theme; tft_rotation = config_readback.eeprom_tft_rotation; mcu_voltage = config_readback.eeprom_mcu_voltage; } void eeprom_write() { // 定义结构变量config,并定义config的内容 config_type config; for (uint8_t a = 0; a < 4; a++) { config.eeprom_correct_min[a] = joy_correct_min[a]; config.eeprom_correct_max[a] = joy_correct_max[a]; } config.eeprom_Joy_deadzone_val = Joy_deadzone_val; config.eeprom_mode_protocol = mode_protocol; #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) config.eeprom_mode_mpu = mode_mpu; #endif config.eeprom_mwc_channal = mwc_channal; config.eeprom_nrf_channal = nrf_channal; config.eeprom_tft_theme = tft_theme; config.eeprom_tft_rotation = tft_rotation; config.eeprom_mcu_voltage = mcu_voltage; // 变量config存储到EEPROM,地址0写入 EEPROM_write(0, config); } </source> joy.h <source lang="cpp"> #include "Arduino.h" #include <Joypad.h> //Joy------------- //1000~2000 uint8_t Joy_deadzone_val = 10; #define Joy_s_maximum 200 //MAX 300 #define Joy_maximum 450 //MAX 500 #define Joy_MID 1500 //1500 boolean mode_mpu, mode_protocol; //{(0: 0 is mwc, 1 is nrf),(1: 0 is mpu, 1 is no mpu)} int16_t joy_correct_max[4], joy_correct_min[4]; int16_t Joy_x, Joy_y, Joy1_x, Joy1_y; int16_t s_lig, s_mic; boolean Joy_sw, Joy1_sw; boolean but1, but2, but3, but4; boolean sw_l, sw_r; //====================================== int16_t Joy_dead_zone(int16_t _Joy_vol) { if (abs(_Joy_vol) > Joy_deadzone_val) return ((_Joy_vol > 0) ? (_Joy_vol - Joy_deadzone_val) : (_Joy_vol + Joy_deadzone_val)); else return 0; } int16_t Joy_i(int16_t _Joy_i, boolean _Joy_b, int16_t _Joy_MIN, int16_t _Joy_MAX) { int16_t _Joy_a; switch (_Joy_i) { case 0: _Joy_a = Joy_dead_zone(Joypad.readJoystickX()); break; case 1: _Joy_a = Joypad.readJoystickY(); //throt break; case 2: _Joy_a = Joy_dead_zone(Joypad.readJoystick1X()); break; case 3: _Joy_a = Joy_dead_zone(Joypad.readJoystick1Y()); break; } if (_Joy_b) { if (_Joy_a < 0) _Joy_a = map(_Joy_a, joy_correct_min[_Joy_i], 0, _Joy_MAX, Joy_MID); else _Joy_a = map(_Joy_a, 0, joy_correct_max[_Joy_i], Joy_MID, _Joy_MIN); if (_Joy_a < _Joy_MIN) _Joy_a = _Joy_MIN; if (_Joy_a > _Joy_MAX) _Joy_a = _Joy_MAX; } return _Joy_a; } void Joy() { sw_l = Joypad.readButton(CH_SWITCH_L); sw_r = Joypad.readButton(CH_SWITCH_R); //------------------------------------ //s_lig=Joypad.readLightSensor(); //s_mic=Joypad.readMicrophone(); //------------------------------------ Joy_sw = Joypad.readButton(CH_JOYSTICK_SW); Joy1_sw = Joypad.readButton(CH_JOYSTICK1_SW); //------------------------------------ but1 = Joypad.readButton(CH_SWITCH_1); but2 = Joypad.readButton(CH_SWITCH_2); but3 = Joypad.readButton(CH_SWITCH_3); but4 = Joypad.readButton(CH_SWITCH_4); #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) //==================================== int16_t y[3]; //MPU--------------------------------- if (mode_mpu) //MPU--------------------------------- { for (uint8_t a = 0; a < 3; a++) { y[a] = ypr[a] * 180 / M_PI; if (y[a] > MPU_maximum) y[a] = MPU_maximum; if (y[a] < -MPU_maximum) y[a] = -MPU_maximum; } } #endif if (Joypad.readButton(CH_SWITCH_R)) { Joy_x = Joy_i(0, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); Joy_y = Joy_i(1, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) if (mode_mpu) //MPU--------------------------------- { Joy1_x = map(y[2], -MPU_maximum, MPU_maximum, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); Joy1_y = map(y[1], -MPU_maximum, MPU_maximum, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); } else #endif { Joy1_x = Joy_i(2, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); Joy1_y = Joy_i(3, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); } } else { Joy_x = Joy_i(0, true, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum); Joy_y = Joy_i(1, true, mode_protocol ? Joy_MID - Joy_s_maximum : Joy_MID - Joy_maximum, mode_protocol ? Joy_MID + Joy_s_maximum : Joy_MID + Joy_maximum); // Robot,QuadCopter #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) if (mode_mpu) //MPU--------------------------------- { Joy1_x = map(y[2], -MPU_maximum, MPU_maximum, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum); Joy1_y = map(y[1], -MPU_maximum, MPU_maximum, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum); } else #endif { Joy1_x = Joy_i(2, true, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum); Joy1_y = Joy_i(3, true, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum); } } } </source> key.h <source lang="cpp"> #include "arduino.h" uint8_t key_pin[4] = {CH_SWITCH_1, CH_SWITCH_2, CH_SWITCH_3, CH_SWITCH_4}; //按键1 2 3 4 boolean key_status[4]; //按键 boolean key_cache[4]; //检测按键松开缓存 void key_init() { for (uint8_t a = 0; a < 4; a++) { key_status[a] = LOW; key_cache[a] = HIGH; } } boolean key_get(uint8_t _key_num, boolean _key_type) { key_cache[_key_num] = key_status[_key_num]; //缓存作判断用 key_status[_key_num] = !Joypad.readButton(key_pin[_key_num]); //触发时 switch (_key_type) { case 0: if (!key_status[_key_num] && key_cache[_key_num]) //按下松开后 return true; else return false; break; case 1: if (key_status[_key_num] && !key_cache[_key_num]) //按下松开后 return true; else return false; break; } } </source> mpu.h <source lang="cpp"> #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) #include "Wire.h" #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" MPU6050 mpu; //MPU------------- #define MPU_maximum 70 // MPU control/status vars boolean dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer // orientation/motion vars Quaternion q; // [w, x, y, z] quaternion container VectorInt16 aa; // [x, y, z] accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector void initMPU() { Wire.begin(); #ifdef Serial_DEBUG Serial.println(F("Initializing I2C devices...")); #endif mpu.initialize(); // verify connection #ifdef Serial_DEBUG Serial.println(F("Testing device connections...")); #endif if (mpu.testConnection()) { #ifdef Serial_DEBUG Serial.println("MPU6050 connection successful"); #endif } #ifdef Serial_DEBUG else Serial.println(F("MPU6050 connection failed")); #endif // load and configure the DMP #ifdef Serial_DEBUG Serial.println(F("Initializing DMP...")); #endif devStatus = mpu.dmpInitialize(); // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it's ready #ifdef Serial_DEBUG Serial.println(F("Enabling DMP...")); #endif mpu.setDMPEnabled(true); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it // Serial.println(F("DMP ready! Waiting for first interrupt...")); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) #ifdef Serial_DEBUG Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); #endif } } void getMPU() { if (!dmpReady) return; { // reset interrupt flag and get INT_STATUS byte mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); #ifdef Serial_DEBUG Serial.println(F("FIFO overflow!")); #endif // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; // display ypr angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //Serial.print("ypr\t"); //Serial.print(ypr[0] * 180/M_PI); //Serial.print("\t"); //Serial.print(ypr[1] * 180/M_PI); //Serial.print("\t"); // Serial.println(ypr[2] * 180/M_PI); } } } #endif </source> mwc.h <source lang="cpp"> #include "Arduino.h" #if defined(__AVR_ATmega128RFA1__) #include <ZigduinoRadio.h> #endif int16_t RCin[8], RCoutA[8], RCoutB[8]; int16_t p; uint16_t read16() { uint16_t r = (inBuf[p++] & 0xFF); r += (inBuf[p++] & 0xFF) << 8; return r; } uint16_t t, t1, t2; uint16_t write16(boolean a) { if (a) { t1 = outBuf[p++] >> 8; t2 = outBuf[p - 1] - (t1 << 8); t = t1; } else t = t2; return t; } typedef unsigned char byte; byte getChecksum(byte length, byte cmd, byte mydata[]) { //三个参数分别为: 数据长度 , 指令代码 , 实际数据数组 byte checksum = 0; checksum ^= (length & 0xFF); checksum ^= (cmd & 0xFF); for (uint8_t i = 0; i < length; i++) { checksum ^= (mydata[i] & 0xFF); } return checksum; } void data_rx() { // s_struct_w((int*)&inBuf,16); p = 0; for (uint8_t i = 0; i < 8; i++) { RCin[i] = read16(); /* Serial.print("RC["); Serial.print(i+1); Serial.print("]:"); Serial.print(inBuf[2*i],DEC); Serial.print(","); Serial.print(inBuf[2*i+1],DEC); Serial.print("---"); Serial.println(RCin[i]); */ // delay(50); // delay in between reads for stability } } void data_tx() { p = 0; for (uint8_t i = 0; i < 8; i++) { RCoutA[i] = write16(1); RCoutB[i] = write16(0); /* Serial.print("RC["); Serial.print(i+1); Serial.print("]:"); Serial.print(RCout[i]); Serial.print("---"); Serial.print(RCoutA[i],DEC); Serial.print(","); Serial.print(RCoutB[i],DEC); Serial.println(""); */ // delay(50); // delay in between reads for stability } } /* if Core RF [head,2byte,0xAA 0xBB] [type,1byte,0xCC] [data,16byte] [body,1byte(from getChecksum())] Example: AA BB CC 1A 01 1A 01 1A 01 2A 01 3A 01 4A 01 5A 01 6A 01 0D ** */ void data_send() { data_tx(); #if !defined(__AVR_ATmega128RFA1__) static byte buf_head[3]; buf_head[0] = 0x24; buf_head[1] = 0x4D; buf_head[2] = 0x3C; #endif #define buf_length 0x10 //16 #define buf_code 0xC8 //200 static byte buf_data[buf_length]; for (uint8_t a = 0; a < (buf_length / 2); a++) { buf_data[2 * a] = RCoutB[a]; buf_data[2 * a + 1] = RCoutA[a]; } static byte buf_body; buf_body = getChecksum(buf_length, buf_code, buf_data); //---------------------- #if defined(__AVR_ATmega128RFA1__) mwc_port.beginTransmission(); mwc_port.write(0xaa); mwc_port.write(0xbb); mwc_port.write(0xcc); #else for (uint8_t a = 0; a < 3; a++) { mwc_port.write(buf_head[a]); } mwc_port.write(buf_length); mwc_port.write(buf_code); #endif for (uint8_t a = 0; a < buf_length; a++) { mwc_port.write(buf_data[a]); } mwc_port.write(buf_body); #if defined(__AVR_ATmega128RFA1__) mwc_port.endTransmission(); #endif } </source> nrf.h <source lang="cpp"> #include "Arduino.h" #include <RF24Network.h> #include <RF24.h> #include <SPI.h> // nRF24L01(+) radio attached using Getting Started board RF24 radio(9, 10); //ce,cs RF24Network network(radio); #define this_node 0 //设置本机ID #define other_node 1 //-------------------------------- struct send_a //发送 { uint32_t ms; uint16_t rf_CH0; uint16_t rf_CH1; uint16_t rf_CH2; uint16_t rf_CH3; uint16_t rf_CH4; uint16_t rf_CH5; uint16_t rf_CH6; uint16_t rf_CH7; }; struct receive_a //接收 { uint32_t node_ms; }; //-------------------------------- unsigned long node_clock, node_clock_debug, node_clock_cache = 0; //节点运行时间、节点响应检查时间、节点时间缓存 //debug-------------------------- boolean node_clock_error = false; //节点响应状态 unsigned long time_debug = 0; //定时器 //====================================== void vodebug() { if (millis() - time_debug > interval_debug) { node_clock_error = boolean(node_clock == node_clock_debug); //一定时间内,节点返回的运行时间若不变则有问题 node_clock_debug = node_clock; time_debug = millis(); } } void nrf_send() { #ifdef Serial_DEBUG Serial.print("Sending..."); #endif send_a sen = { millis(), outBuf[0], outBuf[1], outBuf[2], outBuf[3], outBuf[4], outBuf[5], outBuf[6], outBuf[7] }; //把这些数据发送出去,对应前面的发送数组 RF24NetworkHeader header(other_node); if (network.write(header, &sen, sizeof(sen))) { #ifdef Serial_DEBUG Serial.print("Is ok."); #endif delay(50); network.update(); // If it's time to send a message, send it! while ( network.available() ) { // If so, grab it and print it out RF24NetworkHeader header; receive_a rec; network.read(header, &rec, sizeof(rec)); node_clock = rec.node_ms; //运行时间赋值 } } #ifdef Serial_DEBUG else Serial.print("Is failed."); Serial.println(""); #endif } </source> tft.h <source lang="cpp"> #include "Arduino.h" #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library #include <SPI.h> Adafruit_ST7735 tft = Adafruit_ST7735(5, 4, -1); //cs,dc,rst //-------字体设置,大、中、小 #define setFont_M tft.setTextSize(2) #define setFont_S tft.setTextSize(0) #define tft_width 128 #define tft_height 160 boolean tft_theme = false; //0 is white,1 is black boolean tft_rotation = 1; #define TFT_TOP ST7735_BLACK #define TFT_BUT ST7735_WHITE uint16_t tft_colorA = TFT_BUT; uint16_t tft_colorB = TFT_TOP; uint16_t tft_colorC = 0x06FF; uint16_t tft_colorD = 0xEABF; #define tft_bat_x 24 #define tft_bat_y 12 #define tft_bat_x_s 2 #define tft_bat_y_s 6 #define tft_font_s_height 8 #define tft_font_m_height 16 #define tft_font_l_height 24 #define _Q_x 33 #define _Q_y 36 #define _W_x 93 #define _W_y 5 #define _Q_font_x 2 #define _Q_font_y (_Q_y - 1) int8_t tft_cache = 1; //====================================== void TFT_clear() { tft.fillScreen(tft_colorB); } void TFT_init(boolean _init, boolean _rot) { tft_colorB = tft_theme ? TFT_TOP : TFT_BUT; tft_colorA = tft_theme ? TFT_BUT : TFT_TOP; if (_init) { tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab // Serial.println("init"); tft.fillScreen(tft_colorB); if (_rot) tft.setRotation(2); } tft.fillRect(0, 0, tft_width, 40, tft_colorA); tft.setTextColor(tft_colorB); setFont_M; tft.setCursor(26, 6); tft.print("Joypad"); setFont_S; tft.setCursor(32, 24); tft.print("Microduino"); tft.fillRect(0, 40, tft_width, 120, tft_colorB); } void TFT_begin() { setFont_S; tft.setTextColor(tft_colorA); tft.setCursor(_Q_font_x, 44); tft.println("[key1] enter config"); setFont_M; tft.setCursor(4, 150); for (uint8_t a = 0; a < (millis() - TIME1) / (interval_TIME1 / 10); a++) { tft.print("-"); } } int8_t menu_num_A = 0; int8_t menu_num_B = 0; int8_t menu_sta = 0; #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) char *menu_str_a[5] = { "Joystick Config", "Protocol Config", "System Config", "Gyroscope Config", "Exit" }; #else char *menu_str_a[4] = { "Joystick Config", "Protocol Config", "System Config", "Exit" }; #endif #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) char *menu_str_b[4][3] = { {"Joystick Correct.", "Dead Zone config"}, {"Mode", "Quadrotor Channel", "nRF24 Channel"}, {"TFT Theme", "TFT Rotation", "MCU Voltage"}, {"Gyroscope OFF", "Gyroscope ON"} }; #else char *menu_str_b[3][3] = { {"Joystick Correct.", "Dead Zone config"}, {"Mode", "Quadrotor Channel", "nRF24 Channel"}, {"TFT Theme", "TFT Rotation", "MCU Voltage"}, }; #endif void TFT_menu(int8_t _num, char *_data) { tft.drawRect(7, 49 + 15 * _num, 114, 16, tft_colorA); tft.setCursor(10, 54 + 15 * _num); tft.print(_data); } void TFT_menu(int8_t _num, int16_t _data) { tft.drawRect(7, 49 + 15 * _num, 114, 16, tft_colorA); tft.setCursor(10, 54 + 15 * _num); tft.print(_data); } void TFT_cursor(int8_t _num) { tft.drawLine(1, 51 + 15 * _num, 4, 56 + 15 * _num, tft_colorA); tft.drawLine(4, 57 + 15 * _num, 1, 62 + 15 * _num, tft_colorA); tft.drawLine(1, 51 + 15 * _num, 1, 62 + 15 * _num, tft_colorA); } boolean return_menu = false; boolean TFT_config() { tft.setTextColor( tft_colorA); if (key_get(0, 1)) { menu_sta --; tft_cache = 1; if (menu_sta <= 0) menu_num_B = 0; //zero } if (key_get(1, 1)) { if (return_menu) menu_sta --; else menu_sta ++; tft_cache = 1; } if (menu_sta > 2) menu_sta = 2; if (menu_sta < 0) menu_sta = 0; return_menu = false; //------------------------------- if (tft_cache) tft.fillRect(0, 40, tft_width, 100, tft_colorB); if (menu_sta == 2) { switch (menu_num_A) { case 0: { switch (menu_num_B) { case 0: { if (tft_cache) { for (uint8_t a = 0; a < 4; a++) { joy_correct_min[a] = 0; joy_correct_max[a] = 0; } } for (uint8_t a = 0; a < 4; a++) { tft.setCursor(2, 120); tft.print("Move Joystick MaxGear"); int16_t _c = Joy_i(a, false, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum); if (_c > joy_correct_max[a]) { tft.fillRect(0, 40, tft_width, 100, tft_colorB); joy_correct_max[a] = _c; } // joy_correct_max[a] = constrain(joy_correct_max[a], 0, Joy_maximum); if (_c < joy_correct_min[a]) { tft.fillRect(0, 40, tft_width, 100, tft_colorB); joy_correct_min[a] = _c; } // joy_correct_min[a] = constrain(joy_correct_min[a], -Joy_maximum, 0); } for (uint8_t d = 0; d < 2; d++) { tft.drawFastHLine(12 + 70 * d, 80, 33, tft_colorA); tft.drawFastVLine(28 + 70 * d, 64, 33, tft_colorA); // tft.fillRect(2, 90-4, 20, 12, tft_colorB); tft.drawCircle(44 + 70 * d, 80, map(joy_correct_min[0 + 2 * d], 0, -512, 1, 10), tft_colorA); tft.drawCircle(12 + 70 * d, 80, map(joy_correct_max[0 + 2 * d], 0, 512, 1, 10), tft_colorA); tft.drawCircle(28 + 70 * d, 64, map(joy_correct_min[1 + 2 * d], 0, -512, 1, 10), tft_colorA); tft.drawCircle(28 + 70 * d, 96, map(joy_correct_max[1 + 2 * d], 0, 512, 1, 10), tft_colorA); } return_menu = true; } break; case 1: { if (key_get(2, 1)) { Joy_deadzone_val--; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } if (key_get(3, 1)) { Joy_deadzone_val++; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } Joy_deadzone_val = constrain(Joy_deadzone_val, 0, 25); TFT_menu(0, Joy_deadzone_val); TFT_cursor(0); return_menu = true; } break; } } break; case 1: { switch (menu_num_B) { case 0: { char *menu_str_c[2] = { "Quadro.", "nRF24"}; if (key_get(2, 1) || key_get(3, 1)) { mode_protocol = !mode_protocol; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } for (uint8_t c = 0; c < 2; c++) { TFT_menu(c, menu_str_c[c]); } TFT_cursor(mode_protocol); return_menu = true; } break; case 1: { #if !defined(__AVR_ATmega128RFA1__) char *menu_str_c[5] = {"9600", "19200", "38400", "57600", "115200"}; #endif if (key_get(2, 1)) { mwc_channal--; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } if (key_get(3, 1)) { mwc_channal++; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } #if !defined(__AVR_ATmega128RFA1__) mwc_channal = constrain(mwc_channal, 0, 4); TFT_menu(0, menu_str_c[mwc_channal]); #else mwc_channal = constrain(mwc_channal, 11, 26); TFT_menu(0, mwc_channal); #endif TFT_cursor(0); return_menu = true; } break; case 2: { if (key_get(2, 1)) { nrf_channal--; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } if (key_get(3, 1)) { nrf_channal++; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } nrf_channal = constrain(nrf_channal, 0, 125); TFT_menu(0, nrf_channal); TFT_cursor(0); return_menu = true; } break; } } break; case 2: { switch (menu_num_B) { case 0: { tft_theme = !tft_theme; TFT_init(true, tft_rotation); tft_cache = 1; tft.setTextColor(tft_colorA); menu_sta --; } break; case 1: { tft_rotation = !tft_rotation; TFT_init(true, tft_rotation); tft_cache = 1; tft.setTextColor(tft_colorA); menu_sta --; } break; case 2: { char *menu_str_c[2] = { "3.3V", "5.0V"}; return_menu = true; if (key_get(2, 1) || key_get(3, 1)) { mcu_voltage = !mcu_voltage; tft.fillRect(0, 40, tft_width, 100, tft_colorB); } TFT_cursor(mcu_voltage); for (uint8_t c = 0; c < 2; c++) { TFT_menu(c, menu_str_c[c]); } // tft.fillRect(0, 40, tft_width, 100,tft_colorB); } break; } } break; #if !(defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)) case 3: { //mpu mode_mpu = menu_num_B; tft_cache = 1; menu_sta = 0; //back main menu menu_num_B = 0; //zero } break; #endif } } /* Serial.print(menu_sta); Serial.print(","); Serial.print(menu_num_A); Serial.print(","); Serial.println(menu_num_B); */ //---------------------------- if (menu_sta == 1) { #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) int8_t meun_b_max[5] = {1, 2, 2, 1, 0}; #else int8_t meun_b_max[4] = {1, 2, 2, 0}; #endif if (!meun_b_max[menu_num_A]) return false; else { if (key_get(2, 1)) { tft.fillRect(0, 40, 5, 100, tft_colorB); menu_num_B--; } if (key_get(3, 1)) { tft.fillRect(0, 40, 5, 100, tft_colorB); menu_num_B++; } menu_num_B = constrain(menu_num_B, 0, meun_b_max[menu_num_A]); TFT_cursor(menu_num_B); if (tft_cache) { for (uint8_t b = 0; b < (meun_b_max[menu_num_A] + 1); b++) { TFT_menu(b, menu_str_b[menu_num_A][b]); } } } } //main menu if (menu_sta == 0) { //custer if (key_get(2, 1)) { tft.fillRect(0, 40, 5, 100, tft_colorB); menu_num_A--; } if (key_get(3, 1)) { tft.fillRect(0, 40, 5, 100, tft_colorB); menu_num_A++; } #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) menu_num_A = constrain(menu_num_A, 0, 4); #else menu_num_A = constrain(menu_num_A, 0, 3); #endif TFT_cursor(menu_num_A); if (tft_cache) { #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__) for (uint8_t a = 0; a < 5; a++) { #else for (uint8_t a = 0; a < 4; a++) { #endif TFT_menu(a, menu_str_a[a]); } } } if (tft_cache) { //BACK tft.fillCircle(12, 149, 8, tft_colorA); tft.drawLine(11, 145, 7, 149, tft_colorB); tft.drawLine(7, 149, 11, 153, tft_colorB); tft.drawLine(7, 149, 17, 149, tft_colorB); //ENTER tft.fillCircle(12 + 20, 149, 8, tft_colorA); tft.drawLine(10 + 20, 146, 7 + 20, 149, tft_colorB); tft.drawLine(7 + 20, 149, 10 + 20, 152, tft_colorB); tft.drawLine(7 + 20, 149, 15 + 20, 149, tft_colorB); tft.drawLine(15 + 20, 146, 15 + 20, 149, tft_colorB); //PREV tft.fillCircle(127 - 12, 149, 8, tft_colorA); tft.drawLine(127 - 12, 153, 127 - 8, 149, tft_colorB); tft.drawLine(127 - 12, 153, 127 - 16, 149, tft_colorB); tft.drawLine(127 - 12, 153, 127 - 12, 145, tft_colorB); //NEXT tft.fillCircle(127 - 32, 149, 8, tft_colorA); tft.drawLine(127 - 32, 145, 127 - 28, 149, tft_colorB); tft.drawLine(127 - 32, 145, 127 - 36, 149, tft_colorB); tft.drawLine(127 - 32, 145, 127 - 32, 153, tft_colorB); } tft_cache --; if (tft_cache < 0) tft_cache = 0; return true; } //------------------ #define _C_x_S (_Q_x + 1) #define _C_x_M (_Q_x + ((_W_x + 1) / 2)) #define _C_x_E (_Q_x + _W_x - 1) char *NAME[8] = { "ROLL", "PITCH", "YAW", "THROT", "AUX1", "AUX2", "AUX3", "AUX4" }; void TFT_ready() { tft.fillRect(0, 0, 128, 26, tft_colorA); tft.drawRect(tft_width - tft_bat_x - tft_bat_x_s - 2, 2, tft_bat_x, tft_bat_y, tft_colorB); tft.drawRect(tft_width - tft_bat_x_s - 2, 2 + (tft_bat_y - tft_bat_y_s) / 2, tft_bat_x_s, tft_bat_y_s, tft_colorB); tft.setTextColor(tft_colorB); setFont_S; tft.setCursor(_Q_font_x, 3); tft.print(mode_protocol ? "nRF24" : "Quadr"); tft.print(" CHAN."); tft.print(mode_protocol ? nrf_channal : mwc_channal); tft.setCursor(_Q_font_x, 16); tft.print("Time:"); tft.setTextColor(tft_colorA); for (uint8_t a = 0; a < 8; a++) { tft.setCursor(_Q_font_x, _Q_font_y + a * 15); tft.print(NAME[a]); //------------------------------------------ tft.drawRect(_Q_x, _Q_y + a * 15, _W_x, _W_y, tft_colorA); } } boolean _a = false, _b = false; void TFT_run() { if (outBuf[3] > (Joy_MID - Joy_maximum)) { if (_a) { Joy_time[0] = millis() - Joy_time[1]; _a = false; } Joy_time[1] = millis() - Joy_time[0]; } else _a = true; if (!_b && ((Joy_time[1] / 1000) % 2)) { _b = !_b; tft.fillRect(_Q_font_x + 30, 16, 50, 7, tft_colorA); tft.setTextColor(tft_colorB); tft.setCursor(_Q_font_x + 30, 16); tft.print((Joy_time[1] / 1000) / 60); tft.print("m"); tft.print((Joy_time[1] / 1000) % 60); tft.print("s"); } _b = boolean((Joy_time[1] / 1000) % 2); //battery------------------ tft.fillRect(tft_width - tft_bat_x - 3, 3, map(_V_bat, _V_min, _V_max, 0, tft_bat_x - 2) , tft_bat_y - 2, tft_colorB); tft.fillRect(tft_width - tft_bat_x - 3 + map(_V_bat, _V_min, _V_max, 0, tft_bat_x - 2), 3, map(_V_bat, _V_min, _V_max, tft_bat_x - 2, 0) , tft_bat_y - 2, tft_colorA); for (uint8_t a = 0; a < 8; a++) { int8_t _C_x_A0, _C_x_B0, _C_x_A, _C_x_B, _C_x_A1, _C_x_B1; int8_t _C_x; if (outBuf[a] < Joy_MID) { _C_x = map(outBuf[a], Joy_MID - Joy_maximum, Joy_MID, _C_x_S, _C_x_M); _C_x_A0 = _C_x_S; _C_x_B0 = _C_x - _C_x_S; _C_x_A = _C_x; _C_x_B = _C_x_M - _C_x; _C_x_A1 = _C_x_M; _C_x_B1 = _C_x_E - _C_x_M; } else if (outBuf[a] > Joy_MID) { _C_x = map(outBuf[a], Joy_MID, Joy_MID + Joy_maximum, _C_x_M, _C_x_E); _C_x_A0 = _C_x_S; _C_x_B0 = _C_x_M - _C_x_S; _C_x_A = _C_x_M; _C_x_B = _C_x - _C_x_M; _C_x_A1 = _C_x; _C_x_B1 = _C_x_E - _C_x; } else { _C_x_A0 = _C_x_S; _C_x_B0 = _C_x_M - _C_x_S; _C_x_A = _C_x_M; _C_x_B = 0; _C_x_A1 = _C_x_M; _C_x_B1 = _C_x_E - _C_x_M; } tft.fillRect(_C_x_A0, _Q_y + a * 15 + 1, _C_x_B0, _W_y - 2, tft_colorB); tft.fillRect(_C_x_A, _Q_y + a * 15 + 1, _C_x_B, _W_y - 2, tft_colorC); tft.fillRect(_C_x_A1, _Q_y + a * 15 + 1, _C_x_B1, _W_y - 2, tft_colorB); tft.fillRect(_C_x_M, _Q_y + a * 15 - 1, 1, _W_y + 2, tft_colorD); } //netsta------------------ tft.fillRect(0, 158, 128, 2, node_clock_error ? tft_colorD : tft_colorC); } </source> time.h <source lang="cpp"> #include "Arduino.h" //unsigned long time; unsigned long TIME1; //setup delay unsigned long time2; //send data unsigned long time3; //battery unsigned long Joy_time[2] = {0, 0}; //joy </source> ==视频==
返回至
Cube小车/zh
。
导航菜单
个人工具
创建账户
登录
名字空间
页面
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
Welcome
首页
创客大赛
大赛详情
3D打印
安装月球车
图形化编程
操控月球车
升级月球车
编程工具下载
软件下载
Arduino
Processing
Mixly
Scratch
模块套件
Microduino 102
mCookie 102
mCookie 202
mCookie 302
IBC
其他
应用套件
四轴飞行器
平衡车
小车CUBE
音乐播放器
刷卡音乐播放器
wifi气象站
彩虹音乐触摸灯
分贝检测仪
迎门汇报
LED点阵时钟
LED点阵屏幕
硬件
mCookie
Sensor
Microduino
MicroWrt
MicroNux
MicroRobot-Core
MicroRobot-CoreESP
ideaBoard
ideaBox
MicroMV
MicroAI
帮助
常见问题
帮助
工具
链入页面
相关更改
特殊页面
页面信息