|
|
Line 154: |
Line 154: |
| *The code of the quadcopter:'''[https://github.com/wasdpkj/MultiWii_for_Microduino MultiWii_for_Microduino]''' | | *The code of the quadcopter:'''[https://github.com/wasdpkj/MultiWii_for_Microduino MultiWii_for_Microduino]''' |
| | | |
− | ===Quadcopter Adjustment === | + | ==Programming== |
− | ====Preperation====
| + | *Stack '''[[Microduino-CoreRF]]''' and '''[[Microduino-USBTTL]]''' together. |
− | *Stack the Microduino-CoreRF, Microduino-Motuion and Microduino-USBTTL, then connect them to the base plate. | + | **Connect the '''[[Microduino-USBTTL]]''' with USB cable and prepare to upload the program. |
− | [[File:Microduino_QuadCoptersdfs_Software11.jpg|400px|center]] | + | **Note:You’d better upload the programs before stacking all the modules together. |
| + | *Open the Arduino IDE for Microduino environment(Reference of setting up:'''[[AVR Core:Getting started]]''') |
| + | *Click '''【File】''', confirm '''board card (Microduino-CoreRF)''' selected rightly, and choose the corresponding ''' port number (COMX)'''. |
| + | *Click '''【File】'''->'''【Open】''', browse to the project program address, and click '''“MultiWii_for_CoreRF.ino”''' to open it. |
| + | *After confirming all these are right, click '''"→"''' to download the program to the development board. |
| + | *Microduino-USBTTL download module is used when download programs and debug serial ports and correct the quadcopter, and you can not stack it at other time. |
| | | |
− | *Open the Quadcopter file and select "MultiWiiConf \application.windows32 \MultiWiiConf.exe" to adjust parameters of the Quadcopter.
| + | ==Operating Instructions== |
− | '''Note: The file needs to be opened under JAVA development environment or adopt Microduino_Joypad_QuadCopter\java to install.
| |
| | | |
− | ====Sensor Calibration==== | + | ===Guidance of Correcting the Four Axes=== |
− | *Put the Quadcopter on the desk, click RECONNECT, you'll the curve of the sensor data; Click CALIB_ACC and keep stable of the Quadcopter for 5s, the accelerator will be calibrated; Click WRITE and write the values into the Quadcopter.
| |
| | | |
− | *Click CALIB_MAG and take the Quadcopter to rotate around the modules to calibrate the electronic compass. After that, please put the Quadcopter on a smooth place and click WRITE to write values into the Quadcopter after the compass being balanced. | + | ====Autocorrection(Recommend)==== |
| + | *The default is automatic correction mode, and the manual correction is not needed after programming. |
| | | |
| + | ====Manual Correction==== |
| + | *When the quadcopter can’t correct automatically and the users want to correct by hand, you can refer to the following steps. |
| + | **Stack Microduino-CoreRF, Microduino-10DOF, and Microduino-USBTTL together and install them to the flight control floor. |
| + | [[File:Microduino_QuadCopter_Software11.jpg|400px|center]] |
| + | |
| + | *Open the software |
| + | **According to the system type, open the corresponding MultiWiiConf.exe in the quadcopter folder. |
| + | **'''Note:The file needs to be opened in JAVA development environment, and if you haven’t the JAVA development environment, you can choose the Microduino_Joypad_QuadCopter\java environment to install'''. |
| + | |
| + | *Correction of the Sensor |
| + | **Put the four axis horizontally on the table. |
| + | **Click RECONNECT on the surface on the software, and wait for the sensor data curve appearing. |
| + | **Click CALIB_ACC and keep the four axis stable during the following 5 seconds, and the accelermeter of the flight control will correct. |
| + | **Click WRITE to write number into the flight control. |
| + | **Click CALIB_MAG and then pick up the plane to make it run in circle centering on the module again and again, and place the four axes on smooth place after the correction of the electronic compass. |
| + | **After the electronic compass is balanced, click WRITE to write the number into the flight control. |
| [[File:RF_Pitch_Roll.jpg|center|600px]] | | [[File:RF_Pitch_Roll.jpg|center|600px]] |
| | | |
− | ====PID Parameter Setting ====
| + | *Set the PID Parameter |
− | Click LOAD to load setting files and select pku.mwi to input, as shown below:
| + | ** LOAD configuration file directly, and click LOAD, choose the Microduino.mwi to import, as shown in the picture: |
| [[File:Microduino_QuadCopter_MultiWiiConf4.jpg|600px|center]] | | [[File:Microduino_QuadCopter_MultiWiiConf4.jpg|600px|center]] |
| | | |
− | ====Flying Mode Setting ====
| + | *Set the flight mode. |
− | |-
| + | **On the right side of the adjustment of PID, click ”SELECT SETTING”(as the following figue). |
− | |
| + | **Click the left mouse button on the square, and the grey square will change into white. Click the 3 squares as the following picture(which should be grey originally). |
− | | + | **After setting, click WRITE to write the value into the flight control. |
− | | |
− | Click SELECT SETTING on the right side of the PID, we can see various flight patterns and a two-dimensional table corresponding to the auxiliary switch. A combination of a switch or multiple switches can be specified as a flight mode. We recommend that players follow the following chart to set the flight mode.
| |
− | |-
| |
− | | The setting method is to click the left mouse button in the square. The gray square will become white, such as the figure below by clicking three white squares (this should be gray).
| |
− | |-
| |
− | | This specifies the corresponding flight mode in such a switch position. ANGLE is a steady mode, which helps us to fly the Quadcopter. You can click WRITE to set up the numerical control writing.
| |
− | | |
− |
| |
| [[File:Microduino_QuadCopter_MultiWiiConf_ANGLE.jpg|600px|center]] | | [[File:Microduino_QuadCopter_MultiWiiConf_ANGLE.jpg|600px|center]] |
| | | |
− | Close the MultiWiiConf serial port after setting up the flight mode, you can take down the Microduino-USBTTL module, completing the assembly and debugging of the whole flight controller.
| + | *Use the sensor’s value to remove the debug. |
− | | + | **Make the fuselage lean to the right(the left side upward): |
− | ====Troubleshooting with Sensor Values====
| + | ***The values of MAG_ROLL, ACC_ROLL and GYRO_ROLL increase. |
− | This method can help to eliminate the problem of aircraft in direction. It can be used to display the correct direction of the control board installation or if there is no proper control board type in "config.h".
| + | ***The values of MAG_Z and ACC_Z decrease. |
− | * Tilt to the right side of the fuselage: | + | **Make the fuselage lean forward(the tail lift up): |
− | **MAG_ROLL, ACC_ROLL and GYRO_ROLL values increase | + | ***The values of MAG_PITCH, ACC_PITCH and GYRO_PITCH increase. |
− | **MAG_Z and ACC_Z values reduce | + | ***The values of MAG_Z and ACC_Z decrease. |
− | * Move the fuselage forward (rear up): | + | **Make the fuselage rotate clockwise(yawing): |
− | **MAG_PITCH, ACC_PITCH and GYRO_PITCH values increase | + | ***The value of CYRO_YAW increases. |
− | **MAG_Z and ACC_Z values reduce | + | **The fuselage remains level: |
− | *Turn the fuselage in a clockwise direction (yaw): | + | ***The values of MAG_Z and ACC_Z are positive. |
− | **CYRO_YAW numerical value | |
− | * body level: | |
− | **MAG_Z and ACC_Z values are positive | |
| | | |
− | ==Remote Controller(Microduino-Joypad)Buildup & Debugging==
| + | *Complete the correction |
− | As it mentioned previously, the remote controller is composed of the control board (Microduino-Joypad), the microcontroller (Microduino-CoreRF), thedisplay module (Microduino-TFT) as well as download and debugging module (Microduino-USBTTL).
| + | **Close the connection of serial ports and MultiWiiConf software. |
− | *Microduino Modules | + | **Take down the Microduino-USBTTL module. |
− | {|class="wikitable"
| |
− | |-
| |
− | |Module||Number||Function
| |
− | |-
| |
− | |Microduino-CoreRF||1||Core board
| |
− | |-
| |
− | |Microduino-USBTTL||1||Program download
| |
− | |-
| |
− | |Microduino-Joypad||1||Remote controller
| |
− | |-
| |
− | |Microduino-TFT||1||Display screen
| |
− | |-
| |
− | |2.4G antenna||1||
| |
− | |-
| |
− | |TFT cable||1||
| |
− | |}
| |
| | | |
− | *Other Equipment
| + | ===Guidance of Joypad Remote Controller=== |
− | {|class="wikitable"
| + | *The set up process, you can refer to the following page:'''[https://www.microduino.cn/wiki/index.php/Microduino-Joypad_Getting_start The Guidance of Joypad]''' |
− | |-
| |
− | |Module||Number||Function
| |
− | |-
| |
− | |Rod cover||1||
| |
− | |-
| |
− | |Key cover ||1||
| |
− | |-
| |
− | |Nylon nut||1||
| |
− | |-
| |
− | |Nylon screw ||1||
| |
− | |-
| |
− | |Screwdriver||1||
| |
− | |-
| |
− | |2.4G antenna||1||
| |
− | |-
| |
− | |TFT cable||1||
| |
− | |}
| |
− | [[File:Joypad物料.jpg|center|600px]]
| |
− | ===Joypad Buildup &Debugging===
| |
− | ====Joypad Buildup====
| |
− | *'''Step 1''': Download program for the Microduino-CorRF of Joypad. | |
− | * * open the Joypad_RC program in the MultiWii_CoreRF, select the right board and port for program download after the compiler is finished.
| |
− | [[File:Joypad步1s骤1.jpg|center|600px]]
| |
− | *'''Step 2''': Put the Microduino-TFT on the back of the Microduino-Joypad panel and fixate it with nylon screws, pay attention to the installation direction of Microduino-TFT.
| |
− | [[File:Joypad步骤1.jpg|center|600px]]
| |
| | | |
− | *'''Step 3''':As it is shown in the picture, you can fixate the Joypad with nylon nuts and screws. Insert the 2.4G antenna into Microduino-CoreRF and connect them to the base plate of Microduino-Joypad. | + | *'''Joypad Communication mode configuration'''* |
− | [[File:Joypad步骤2.jpg|center|600px]] | + | *The mode configuration, you can refer to the following page:'''[https://www.microduino.cn/wiki/index.php/Microduino-Joypad_Getting_start/zh#.E9.80.9A.E8.AE.AF.E6.A8.A1.E5.BC.8F Communication mode configuration]''' |
| + | **When we use '''[[Microduino-CoreRF]]''' as '''communication''', the Joypad correspondingly choose '''“Quadro.”''' |
| | | |
− | *'''Step 4''':Connect Microduino-TFT and Microduino-Joypad with cables. | + | *'''Joypad battery instruction'''* |
− | [[File:Joypad步骤3.jpg|center|600px]]
| + | *Special attention should be paid to the battery instructions:'''[https://www.microduino.cn/wiki/index.php/Microduino-Joypad_Getting_start #Step-3_.E7.94.B5.E6.B1.A0.E9.80.9A.E7.94.B5 Battery instruction]''' |
− | *'''Step 5''':Put the switch on the battery to the side of "Dry bat(1.5V)", install the battery (AAA battery) to the battery box; Open the switch on the right side of the Joypad to see if it is powered. If not, please use the USB data cable to connect to the left of the MicroUSB interface to activate the system. | |
− | |-
| |
− | |You can also not use the battery. The power supply can also be achieved through a USB cable.
| |
− | [[File:Joypad步骤4.jpg|center|600px]]
| |
| | | |
− | *'''Step 6''':Use nylon screws to fix the bottom plate and the panel. The remote sensing cap is installed on the rocker, and the button cap is installed on the button. (If the key is not connected well with the upper plate of the key, you can insert the key into the key interface, and then connect with the bottom button. | + | ====Joypad unlock the four axes==== |
− | [[File:Joypad步骤5.jpg|center|600px]] | + | *'''Method 1''': |
| + | **Place the four axes o smooth place and turn on the switch. |
| + | **Dial the switch on the left side of the Joypad controller to the bottom(shut down the accelerator), and dial the right switch to top(Reaching the maximum amplitude can it be unlocked.). |
| + | **Pull the throttle rocker to the minimum, and move to the right and wait for about 2s. If the blue led lights for a long time, it shows that unlock successfully, or put the throttle rocker in the middle and then operate again. |
| + | **If you fail to unlock for many times, reset the core of the quadcopter, and try to unlock again. |
| + | [[File:Microduino12_Joypad1_ config5-quad.jpg|400px|center]] |
| | | |
− | *'''Step 7''':You can open the power switch and see if is the power supply is normal. | + | *'''Method 2'': |
− | [[File:Joypad步骤6.jpg|center|600px]]
| + | **Dial the left and right to the top. |
| + | **Pull the throttle rocker to the bottom. |
| + | **Pressing the right stick can switch the quadcopter locking / unlocking state. |
| | | |
− | ====Joypad Buildup Debugging==== | + | ====Joypad Controls the Quadcopter==== |
− | *Key
| + | *Pull the throttle rocker to the bottom again. |
− | Press the Key 1 in 4s after opening the Joypad and enter (Config) mode.
| + | *Push the top left switch up(open the throttle switch). |
− | [[File:Step1按键对应.jpg|600px|center|]]
| + | *At the first using, you’d better adjust precision adjustment switch to dialed to the bottom to make the flight more stable. |
− | *Enter setting mode
| |
− | Key1 to Key 4 from the left to the right as shown below:
| |
− | [[File:Step001进入设置.jpg|600px|center|]]
| |
− | Note: Make sure setting before entering the OS interface.
| |
− | *Joystick calibration
| |
− | Press Key3 and Key4 to move the cursor. The Key 1 refers to "Return" and the Key 2 refers to "Confirm".
| |
− | Select the first item Joystick Config to enter the setting mode and the Joystick Correct to enter the calibration mode.
| |
− | After that, you'll see interface shown in the third picture.
| |
− | At this time, you can swing the rocker to the upmost and watch the results.
| |
− | [[File:Step2摇杆校准.jpg|600px|center|]]
| |
− | *Select control mode
| |
− | Press Key1 to return to the main interface and select Protocol Config to enter mode selection.
| |
− | Choose Mode and then Quadcopter mode, press Key 2 to confirm and return.
| |
− | [[File:Step3设置四轴模式.jpg|600px|center|]]
| |
− | *Set communication channel
| |
− | Return to the secondary menu, choose Quadcopter Channel and press Key 2 to confirm.
| |
− | Select 12, which corresponds to the setting of "#define RF_Channel 12" under MultiWii.
| |
− | [[File:Step4通信通道设置.jpg|600px|center|]]
| |
− | At this point, the flight controller and remote control has been assembled and the next is to combine the two and begin to test flying. Not only to practice using the joystick, but also to observe the actual flight of the aircraft to further optimize the parameters of PID.
| |
− | | |
− | ===Overall Debugging===
| |
− | *'''Step 1''':Open the switch on the Microduino-QuadCopter, put it in a stable place and press the reset button, the system will calibrate the sensor, the LED light will flash on the unfinished board and go out after the calibration. At this time, please wait to unlock. If the LED lamp has been flashing, meaning the four axis is not calibrated well, please re-calibrate. | |
− | *Unlock the Quadcopter | |
− | **Please dial the Joypad remote control switch to the left side (Close the throttle) to prevent the accident caused by Quadcopter speeding up after unlocking. The switch on the right is allocated to the top (Unlock until reaching the maximum value11).
| |
− | ** Pull the throttle rocker to the lowest level and wait around 2s, and the brightness of the blue LED means successful unlocking. So you can be ready to fly the aircraft, or put the throttle rocker in the middle and operate again. If you try to unlock for many times and still fail, the n please reset the core module, calibrate the sensor and try to unlock again. | |
− | [[File:Microduino12_Joypad1_ config5-quad.jpg|400px|center]]
| |
− | ** And then put the throttle rocker to the bottom and the left upper switch the top (open the throttle switch), For the first use, it is suggested to dial the switch downside and make sure a stable flying.
| |
| [[File:Microdu1ino12_Joypad1_ config5-quad.jpg|400px|center]] | | [[File:Microdu1ino12_Joypad1_ config5-quad.jpg|400px|center]] |
| + | *Gently push the throttle to make the four propellers roll. |
| + | *Step on the gas and make it not close to the ground. |
| + | *And control balance through the azimuth joystick. |
| + | [[File:Microduino_QuadCopter_Remote6.jpg|600px|center]] |
| + | *Caution of operation |
| + | **Open (dial it to the top) the top left throttle control switch to control, and you can shake the rocker and observe the change on the screen. |
| + | **The switch on the right is a precision adjustment switch, and dial it to the top can get the greatest control to it, or you can only control it in a small degree, and the small degree is helpful to stable control. |
| + | **The left rocker controls the throttle in vertical direction. The higher it is, the greater the throttle is. And the bigger the power is, the higher it flies. And it controls the quadcopter in horizontal direction to roll in horizontal direction. |
| + | **The right rocker controls the throttle to move back and forth in vertical direction. Up is to forth, and down is to back. And it controls the throttle to move to left and right in horizontal direction. |
| | | |
− | * You only need to gently push the throttle to see the beginning of the four propellers. Keeping speeding up make sure it's flying. A little higher will be OK, just do not close to the ground, and then keep balance through the joystick.
| |
− | [[File:Microduino_QuadCopter_Remote6.jpg|600px|center]]
| |
− | * In the upper left is the throttle control switch, you can open (dial above) it to control, you can shake the joystick to observe the change of the screen.
| |
− | * The right switch is a precision adjustment switch.
| |
− | *The Joystick in the left controls speeding up in the vertical direction.
| |
− | * The Joystick in the right controls flying in the vertical direction, which controls left and right flying in the horizontal direction.
| |
− |
| |
− | ===Phone Bluetooth Control ===
| |
− | *Get prepared.
| |
− | **Make sure the serial port of the BT and the Serial0 (D0,D1) of the Quadcopter as well as the baud rate (115200).
| |
− | :[[file:Microduino-BT-1Big2.jpg|800px|center|Microduino-BT]]
| |
− | <br style="clear: left"/>
| |
− | **Download APP.
| |
− | [[File:Qua_app.gif|center]]
| |
− | *Debug.
| |
− | Connect the BT module onto the calibrated Quadcopter, then put them on a smooth place and wait for Bluetooth connection.
| |
− |
| |
− | Open the phone Bluetooth and the Quadcopter control APP, you'll see Microduino Bluetooth device.
| |
− | [[File:app_microduino.png|center|600px]]
| |
− | Click Microduino, connect the Bluetooth and enter the control interface. After the connection, it'll show "Ready" to remind you to unlock the Quadcopter.
| |
− | [[File:Qua_app-ready.png|center|600px]]
| |
− | Unlock the Quadcopter: If the Bluetooth indicator on the bottom of the Quadcopter goes on, it means unlocked successfully. If you see "Unlocked" on the screen, please try to unlock again.
| |
− | After unlocking, the middle rod can push up to speed up and the Quadcopter can fly.
| |
− | [[File:Qua_app-ok.png|center|600px]]
| |
− |
| |
− | ==Code & Notes==
| |
| ==Program Description== | | ==Program Description== |
− |
| |
− | ==Joypad Program & Description==
| |
− | 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(); //Initialize 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();
| |
− | }
| |
− |
| |
− | //Node checking -------------------------------
| |
− | 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 //Interval for node checking.
| |
− | uint8_t nrf_channal = 70; //0~125
| |
− |
| |
− | //Battery---------
| |
− | #define PIN_bat A7 //BAT
| |
− |
| |
− | #define _V_max 41 //Maximum voltage for the lithium battery: 4.2V
| |
− | #define _V_min 36 //Minimum voltage for the lithium battery: 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 reads the assigned values.
| |
− | 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()
| |
− | {
| |
− | // Define structure variable "config" as well as the content of the variable.
| |
− | 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;
| |
− |
| |
− | // Save the variable "config" into EEPROM and write in address 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}; //Key (1,2,3,4)
| |
− |
| |
− | boolean key_status[4]; //Key
| |
− | boolean key_cache[4]; //Detect the key releasing cache.
| |
− |
| |
− | 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]; //Cache as a judge
| |
− |
| |
− | key_status[_key_num] = !Joypad.readButton(key_pin[_key_num]); //When it is triggered
| |
− |
| |
− | switch (_key_type)
| |
− | {
| |
− | case 0:
| |
− | if (!key_status[_key_num] && key_cache[_key_num]) //After pressing down and releasing
| |
− | return true;
| |
− | else
| |
− | return false;
| |
− | break;
| |
− | case 1:
| |
− | if (key_status[_key_num] && !key_cache[_key_num]) // After pressing down and releasing
| |
− |
| |
− | 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 fifoCache[64]; // FIFO storage cache
| |
− |
| |
− | // 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(fifoCache, 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, fifoCache);
| |
− | 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[])
| |
− | {
| |
− | //Three parameters including data length, instruction code and the actual data array.
| |
− | 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 //Set ID for the machine.
| |
− | #define other_node 1
| |
− |
| |
− | //--------------------------------
| |
− | struct send_a //Send
| |
− | {
| |
− | 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 //Receive
| |
− | {
| |
− | uint32_t node_ms;
| |
− | };
| |
− |
| |
− | //--------------------------------
| |
− | unsigned long node_clock, node_clock_debug, node_clock_cache = 0; // Node running time, node response checking time and node time cache.
| |
− | //debug--------------------------
| |
− | boolean node_clock_error = false; //Node response status
| |
− | unsigned long time_debug = 0; //Timer
| |
− |
| |
− |
| |
− | //======================================
| |
− | void vodebug()
| |
− | {
| |
− | if (millis() - time_debug > interval_debug)
| |
− | {
| |
− | node_clock_error = boolean(node_clock == node_clock_debug); //Within a certain, if you find the running time of the node returning unchanged, then it has problem.
| |
− |
| |
− | 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]
| |
− | }; //Send out the data, corresponding to the previous array.
| |
− | 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; //Assign values for the running time.
| |
− | }
| |
− | }
| |
− | #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
| |
− | //-------Set front(Large, medium, small)
| |
− | #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>
| |
| | | |
| ==Attention== | | ==Attention== |
| + | Although the above contents list a lot of problems that should be paid attention to, they need to be summarized here. |
| *For installation | | *For installation |
− | **The four propellers must be installed in order. | + | **The four propellers of the quadcopter are installed in order. If you install wrongly, it is likely to lead to that the aircraft can’t fly. |
− | **Electrode for the Lithium battery:Please be noted that the red wire points to the positive pole and the black wire points to the negative pole. | + | **The positive and negative of the lithium battery. The red line is for the positive pole, and the black line is for the negative pole. The circuit is easy to burn out once connect wrongly. Especially when supply power to Microduino-Joypad, because there is no design for avoiding plugging inversely, it should be noted. |
− | *For parameter adjustment | + | *For adjustment of the parameters |
− | **Please refer to the fourth section of the content to adjust the aircraft PID parameters and flight mode, which can be modified according to the recommended configurations. If you want to change PID parameters manually, please choose to change one parameter each time. | + | **Refer to the content of section 4 to adjust the PID parameter of the aircraft and the flight mode. And you’d better modify them on the basis of the recommended configuration. If you want to manually modify the PID parameters, you’d better modify one parameter at one time, otherwise it is difficult to see which parameters work. |
− | *About debugging | + | *For debugging |
− | **Please adjust the Microduino-Joypad and the Quadcopter before flying. | + | **You must correct the controller(Microduino-Joypad)and aircraft, or it is easy to cause the aircraft flying unstably. |
− | *About flying control | + | *For the flight control |
− | **Make sure flying in an empty place. | + | **You must choose an empty place to test, such as the playground in the school, and larger lawn in the park. |
− | **Please turn the switch(on the top left) downside before unlocking the remote controller(Shut off the throttle) and set the throttle to the lowest before flying for fear of the take-off accident. | + | **Before unlocking with the remote controlled, please dial the top left switch to the bottom(close the throttle), and when start the test, please turn the throttle to the lowest at first to avoid accidents. |
− | *Please cut off the power supply of the Quadcopter firstly and the remote controller in order or it'll make the Quadcopter out of control. | + | *If you want to turn off the aircraft, you must switch off the power of the quadcopter, and then switch off the power of the remote controller, or the quadcopter will be out of control, and it is easy to cause accidents. |
| + | *For charging/dry battery |
| + | **The aircraft plate has the function of charge the battery of the aircraft directly, so you only need to plug the USB cable to supply power to the baseboard directly. |
| + | **Joypad adopts dry battery to supply power, and you should dial the battery selection switch to Dry bat. Set up the dry battery, and on supplying power to joypad with USB cable, '''pull out at once'''(It can’t be charged with USB cable for a long time after installing the dry battery), then you can successfully activate the dry battery to supply power. |
| + | If other problems appear, please put forward in the discussion part. |
| |} | | |} |