<?xml version="1.0"?>
<rss version="2.0">
   <channel>
      <title>clybot C6 by Chris Yang</title>
      <link>https://padlet.com/chrisyang/c6</link>
      <description>Arduino</description>
      <language>en-us</language>
      <pubDate>2017-10-23 18:43:26 UTC</pubDate>
      <lastBuildDate>2026-03-03 07:21:43 UTC</lastBuildDate>
      <webMaster>hello@padlet.com</webMaster>
      <image>
         <url>https://padlet-assets.s3.amazonaws.com/icons/Rafaelo.png</url>
      </image>
      <item>
         <title></title>
         <author>chrisyang</author>
         <link>https://padlet.com/chrisyang/c6/wish/199745223</link>
         <description><![CDATA[<div><a href="https://www.youtube.com/c/circuitfly">https://www.youtube.com/c/circuitfly</a></div>]]></description>
         <enclosure url="https://padletuploads.blob.core.windows.net/prod/133566770/8e89f6a15637953b1d1b6fba019cacb0/25__.jpg" />
         <pubDate>2017-10-23 18:53:41 UTC</pubDate>
         <guid>https://padlet.com/chrisyang/c6/wish/199745223</guid>
      </item>
      <item>
         <title></title>
         <author>chrisyang</author>
         <link>https://padlet.com/chrisyang/c6/wish/199745793</link>
         <description><![CDATA[]]></description>
         <enclosure url="https://padletuploads.blob.core.windows.net/prod/133566770/7c15df3d8301c0df28b7de07f20ec744/2016_11_22_V8.jpg" />
         <pubDate>2017-10-23 18:55:05 UTC</pubDate>
         <guid>https://padlet.com/chrisyang/c6/wish/199745793</guid>
      </item>
      <item>
         <title></title>
         <author>chrisyang</author>
         <link>https://padlet.com/chrisyang/c6/wish/199747224</link>
         <description><![CDATA[<div>/*<br>&nbsp; 电路飞翔 - clybot C6寻线自平衡机器人套件<br>&nbsp; circuitfly - clybot C6 line follower self-balancing robot kit<br><br>&nbsp; 3.8-带记忆功能的自平衡机器人<br>&nbsp; 3.8-Self-balancing robot with EEPROM<br><br><br>&nbsp; 功能说明:<br>&nbsp; Functionality:<br>&nbsp; 在3.7实验的基础上，使用EEPROM对平衡点进行保存。这样，当clybot C6<br>&nbsp; 断电上再通电，平衡点可以保存着，不需要每次都设置。<br>&nbsp; Based on the 3.7, EEPROM will be used to store the balancing point.<br>&nbsp; When the clybot C6 powers off and on again, no need to set the<br>&nbsp; balancing point again.<br><br><br>&nbsp; 电路说明：<br>&nbsp; circuit:<br>&nbsp; 直流电机、液晶屏等外设的连接如下：<br>&nbsp; The connections between the peripherals and the Arduino are:<br>&nbsp; &nbsp; LCD&nbsp; &nbsp; &nbsp; &nbsp; Arduino<br>&nbsp; &nbsp; &nbsp;|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br>&nbsp; &nbsp; CS&nbsp; &nbsp; &nbsp; &nbsp; -- 10<br>&nbsp; &nbsp; DC&nbsp; &nbsp; &nbsp; &nbsp; -- 8<br>&nbsp; &nbsp; RST&nbsp; &nbsp; &nbsp; &nbsp;-- 12<br>&nbsp; &nbsp; MOSI(SDA) -- 11<br>&nbsp; &nbsp; SCLK(SCK) -- 13<br><br>&nbsp; &nbsp; LED&nbsp; &nbsp; &nbsp; &nbsp;-- 6<br>&nbsp; &nbsp; Speaker &nbsp; -- A3<br>&nbsp; &nbsp; LDR_L&nbsp; &nbsp; &nbsp;-- A0<br>&nbsp; &nbsp; LDR_R&nbsp; &nbsp; &nbsp;-- A1<br>&nbsp; &nbsp; Button_L&nbsp; -- 1<br>&nbsp; &nbsp; Button_R&nbsp; -- 0<br>&nbsp; &nbsp; BT TXD&nbsp; &nbsp; -- A3<br>&nbsp; &nbsp; BT RXD&nbsp; &nbsp; -- 1<br><br><br>&nbsp; 该程序由电路飞翔设计<br>&nbsp; by circuitfly<br><br>&nbsp; 更多资源请访问：www.clybot.com<br>&nbsp; More info on: www.clybot.com<br>*/<br><br>#include &lt;Adafruit_GFX.h&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//声明包含核心图形库 //Core graphics library<br>#include &lt;Adafruit_ST7735.h&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //声明包含特有硬件库 //Hardware-specific library<br>#include &lt;Fonts/FreeSansBold9pt7b.h&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //声明包含字体&nbsp; //Font&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>#include &lt;Wire.h&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//声明包含I2C通信库 //I2C library<br>#include &lt;Kalman.h&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//声明包含Kalman库 //Kalman library<br>#include &lt;EEPROM.h&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//声明包含EEPROM库&nbsp; //EEPROM library<br><br>#define TFT_CS&nbsp; &nbsp; &nbsp;10&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//液晶屏管脚连接定义&nbsp; //LCD pin collection<br>#define TFT_RST&nbsp; &nbsp; 12<br>#define TFT_DC&nbsp; &nbsp; &nbsp;8<br><br>//周期性循环设置&nbsp; //Set the run cycle<br>#define runEvery(t) for (static long _lasttime;\<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(uint16_t)((uint16_t)millis() - _lasttime) &gt;= (t); \<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_lasttime += (t))<br><br>int SPEAKER = A3;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//SPEAKER变量指向管脚A3控制扬声器&nbsp; //Assign the Pin A3 to variable SPEAKER to control the speaker<br>int MOT_L_EA = 5;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//左侧电机使能端由管脚5控制&nbsp; //The Pin 5 controls the enable of the left motor<br>int MOT_L_1 = 7;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //左侧电机两个端子由管脚7和9控制&nbsp; //The Pin 7 &amp; 9 control the terminals of the left motor<br>int MOT_L_2 = 9;<br>int MOT_R_EA = 3;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//右侧电机使能端由管脚3控制&nbsp; //The Pin 3 controls the enable of the right motor<br>int MOT_R_1 = 4;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //右侧电机两个端子由管脚4和2控制&nbsp; //The Pin 4 &amp; 2 control the terminals of the right motor<br>int MOT_R_2 = 2;<br>int LED = 6;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //LED变量指向管脚6控制发光二极管&nbsp; //Assign the Pin 6 to LED to control the LED<br>int Button_L = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//Button_L变量指向管脚0接收左按钮开关信号&nbsp; //Assign the Pin 0 to Button_L to receive the left pushbutton<br>int Button_R = 1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//Button_R变量指向管脚1接收右按钮开关信号&nbsp; //Assign the Pin 1 to Button_R to receive the right pushbutton<br><br>const int MPU_addr = 0x68;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //MPU6050传感器寻址&nbsp; //I2C address of the MPU6050<br><br>//与按钮开关有关的变量&nbsp; //Set up pushbutton variables<br>int Button_L_lastState = LOW;<br>int Button_R_lastState = LOW;<br>int Button_L_state;<br>int Button_R_state;<br><br>//与加速度计有关的变量&nbsp; //Set up accelerometer variables<br>int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;<br>int16_t accValX, accValY, accValZ;<br>float accBiasX, accBiasY, accBiasZ;<br>float accAngleX, accAngleY;<br>double accRoll;<br><br>//与陀螺仪有关的变量 //Set up gyroscope variables<br>int16_t gyroX, gyroY, gyroZ;<br>float gyroBiasX, gyroBiasY, gyroBiasZ;<br>float gyroRateX, gyroRateY, gyroRateZ;<br>float gyroBias_oldX, gyroBias_oldY, gyroBias_oldZ;<br>float gyroRoll = -180;<br>int x;<br>int y;<br>int z;<br>double Setpoint;<br><br>//设置计时器变量 //Set up a timer Variable<br>uint32_t timer;<br><br>//设置前后倾斜、左右倾斜角度变量 //Set up pitch and roll value variables<br>double InputRoll;<br><br>//设置初始的前后倾斜、左右倾斜角度变量&nbsp; //Set up initial pitch and roll value variables<br>double RollInitial;<br><br>//新建液晶屏实例tft&nbsp; //Create an LCD instant tft<br>Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,&nbsp; TFT_DC, TFT_RST);<br><br>//新建kalman实例&nbsp; //Set up kalman instances<br>Kalman kalmanRoll;<br><br>//与液晶屏显示相关变量&nbsp; //Set up LCD display variables<br>extern unsigned int Self_balancing[1920];<br>extern unsigned int Save[361];<br>uint16_t clybot_r, clybot_b;<br><br>/*<br>&nbsp; &nbsp;显示字符函数 The function for displaying character string<br>*/<br>void drawtext(const char *text, uint16_t color, const GFXfont * font, int cursor_x, int cursor_y) {<br>&nbsp; tft.setFont(font);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //设置字体&nbsp; //Set the font<br>&nbsp; tft.setCursor(cursor_x, cursor_y);&nbsp; &nbsp; &nbsp; &nbsp; //设置光标位置&nbsp; //Set the cursor<br>&nbsp; tft.setTextColor(color);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //设置颜色&nbsp; //Set the colour<br>&nbsp; tft.setTextWrap(true);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //设置自动换行&nbsp; //Set allowing text wrap<br>&nbsp; tft.print(text);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //打字&nbsp; //Print the string<br>}<br><br>/*<br>&nbsp; &nbsp;设备初始化函数 Device initialisation<br>*/<br>void initiateDevice() {<br>&nbsp; Wire.begin();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//启动I2C&nbsp; //Start the I2C<br>&nbsp; Wire.beginTransmission(MPU_addr);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//开始传输&nbsp; //Begin transmission<br>&nbsp; Wire.write(0x6B);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//写电源管理寄存器&nbsp; //PWR_MGMT_1 register<br>&nbsp; Wire.write(0);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //唤醒MPU6050 //set to zero (wakes up the MPU6050)<br>&nbsp; Wire.endTransmission(true);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//结束传输&nbsp; //End transmission<br><br>&nbsp; //设置输出管脚&nbsp; //Set output pins<br>&nbsp; pinMode(MOT_L_EA, OUTPUT);<br>&nbsp; pinMode(MOT_L_1, OUTPUT);<br>&nbsp; pinMode(MOT_L_2, OUTPUT);<br>&nbsp; pinMode(MOT_R_EA, OUTPUT);<br>&nbsp; pinMode(MOT_R_1, OUTPUT);<br>&nbsp; pinMode(MOT_R_2, OUTPUT);<br>&nbsp; pinMode(LED, OUTPUT);<br>}<br><br>/*<br>&nbsp; &nbsp;电机控制函数 Motor control function<br>*/<br>void MotorControl(double out) {<br>&nbsp; if (out &gt; 0) {<br>&nbsp; &nbsp; //正转&nbsp; //Move forward<br>&nbsp; &nbsp; digitalWrite(MOT_R_1, HIGH);<br>&nbsp; &nbsp; digitalWrite(MOT_R_2, LOW);<br>&nbsp; &nbsp; digitalWrite(MOT_L_1, LOW);<br>&nbsp; &nbsp; digitalWrite(MOT_L_2, HIGH);<br>&nbsp; } else {<br>&nbsp; &nbsp; //反转&nbsp; //Move backward<br>&nbsp; &nbsp; digitalWrite(MOT_R_1, LOW);<br>&nbsp; &nbsp; digitalWrite(MOT_R_2, HIGH);<br>&nbsp; &nbsp; digitalWrite(MOT_L_1, HIGH);<br>&nbsp; &nbsp; digitalWrite(MOT_L_2, LOW);<br>&nbsp; }<br>&nbsp; byte vel = abs(out);<br>&nbsp; if (vel &lt; 0)&nbsp; vel = 0;<br>&nbsp; if (vel &gt; 255)&nbsp; vel = 255;<br>&nbsp; analogWrite(MOT_R_EA, vel);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//PWM控制：变量vel的数值越大，电机转速越快&nbsp; //PWM control: higher vel, faster motors<br>&nbsp; analogWrite(MOT_L_EA, vel);<br><br>&nbsp; analogWrite(LED, (255 - vel));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //控制发光二极管亮度&nbsp; //Control LED brightness<br>&nbsp; //if (vel &lt; 80) tone(SPEAKER, vel * 30);&nbsp; //控制扬声器音调&nbsp; //Control the speaker tone<br>&nbsp; //else noTone(SPEAKER);<br>}<br><br>/*<br>&nbsp; &nbsp;获得传感器数值函数 Update sensor data<br>*/<br>void getGyroValues() {<br>&nbsp; Wire.beginTransmission(MPU_addr);<br>&nbsp; Wire.write(0x3B);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//写加速度输出寄存器ACCEL_XOUT_H //Starting with register 0x3B (ACCEL_XOUT_H)<br>&nbsp; Wire.endTransmission(false);<br>&nbsp; Wire.requestFrom(MPU_addr, 14, true); //从MPU6050中获得14个寄存器 //Request a total of 14 registers<br>&nbsp; AcX = Wire.read() &lt;&lt; 8 | Wire.read(); //0x3B (ACCEL_XOUT_H) &amp; 0x3C (ACCEL_XOUT_L)<br>&nbsp; AcY = Wire.read() &lt;&lt; 8 | Wire.read(); //0x3D (ACCEL_YOUT_H) &amp; 0x3E (ACCEL_YOUT_L)<br>&nbsp; AcZ = Wire.read() &lt;&lt; 8 | Wire.read(); //0x3F (ACCEL_ZOUT_H) &amp; 0x40 (ACCEL_ZOUT_L)<br>&nbsp; Tmp = Wire.read() &lt;&lt; 8 | Wire.read(); //0x41 (TEMP_OUT_H) &amp; 0x42 (TEMP_OUT_L)<br>&nbsp; x = Wire.read() &lt;&lt; 8 | Wire.read(); &nbsp; //0x43 (GYRO_XOUT_H) &amp; 0x44 (GYRO_XOUT_L)<br>&nbsp; y = Wire.read() &lt;&lt; 8 | Wire.read(); &nbsp; //0x45 (GYRO_YOUT_H) &amp; 0x46 (GYRO_YOUT_L)<br>&nbsp; z = Wire.read() &lt;&lt; 8 | Wire.read(); &nbsp; //0x47 (GYRO_ZOUT_H) &amp; 0x48 (GYRO_ZOUT_L)<br>}<br><br>/*<br>&nbsp;* 显示倾斜角函数 Function for displaying the roll angle<br>&nbsp;*/<br>void rollDisplay(double roll) {<br>&nbsp; tft.fillRect(55, 85, 48, 19, clybot_b);<br>&nbsp; tft.drawCircle(99, 89, 2, ST7735_WHITE);<br>&nbsp; String Inroll = String(roll);<br>&nbsp; char InrollPrintout[7];<br>&nbsp; Inroll.toCharArray(InrollPrintout, 7);<br>&nbsp; drawtext(InrollPrintout, ST7735_WHITE, &amp;FreeSansBold9pt7b, 55, 100);<br>}<br><br>/*<br>&nbsp; &nbsp;计算倾斜角函数 Calculate the roll angle<br>*/<br>void getRoll() {<br>&nbsp; getGyroValues();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //获得更新的传感器数据&nbsp; //Get updated sensor data<br>&nbsp; accRoll = (atan2(AcY, -AcZ) + PI) * RAD_TO_DEG; //获得倾斜角&nbsp; //Get the roll angle<br>&nbsp; if (accRoll &lt;= 360 &amp; accRoll &gt;= 180)&nbsp; accRoll = accRoll - 360;<br>&nbsp; gyroRateX = ((int)x - gyroBiasX) * .0105;<br>&nbsp; gyroRateY = -((int)y - gyroBiasY) * .0105;<br>&nbsp; gyroRateZ = ((int)z - gyroBiasZ) * .0105;<br>&nbsp; gyroRoll += gyroRateX * ((double)(micros() - timer) / 1000000);<br>&nbsp; RollInitial = kalmanRoll.getAngle(accRoll, gyroRoll, (double)(micros() - timer) / 1000000);<br>&nbsp; rollDisplay(RollInitial);<br>&nbsp; timer = micros();<br>&nbsp; Setpoint = 0;<br>}<br><br>/*<br>&nbsp; &nbsp;计算在C6移动前的MPU6050的数值&nbsp; Calculate bias for the Gyro i.e. the values it gives when it's not moving<br>*/<br>void calculateBias() {<br>&nbsp; for (int i = 1; i &lt; 100; i++) { &nbsp; //循环100次后取平均&nbsp; //Repeat 100 times and average<br>&nbsp; &nbsp; getGyroValues();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //获得传感器MPU6050的原始数据&nbsp; //Obtain original data from the MPU6050<br>&nbsp; &nbsp; gyroBiasX += x;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//把陀螺仪的x,y,z数值进行累加&nbsp; //Accumulate the x, y, z values in the gyro<br>&nbsp; &nbsp; gyroBiasY += y;<br>&nbsp; &nbsp; gyroBiasZ += z;<br>&nbsp; &nbsp; delay(1);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//延时1毫秒&nbsp; //Delay for 1 ms<br>&nbsp; }<br>&nbsp; gyroBiasX = gyroBiasX / 100;&nbsp; &nbsp; &nbsp; //把数值进行平均&nbsp; //Average all the values<br>&nbsp; gyroBiasY = gyroBiasY / 100;<br>&nbsp; gyroBiasZ = gyroBiasZ / 100;<br><br>&nbsp; getGyroValues();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //获得传感器MPU6050的原始数据&nbsp; //Obtain original data from the MPU6050<br>&nbsp; accRoll = (atan2(AcY, -AcZ) + PI) * RAD_TO_DEG;<br><br>&nbsp; if (accRoll &lt;= 360 &amp; accRoll &gt;= 180) accRoll = accRoll - 360; &nbsp; //对超范围值的处理&nbsp; //Process values outside the range<br><br>&nbsp; //设置kalman起始角度// Set starting angle for Kalman<br>&nbsp; kalmanRoll.setAngle(accRoll);<br>&nbsp; kalmanRoll.setQangle(0.01);<br>&nbsp; kalmanRoll.setQbias(0.0003);<br>&nbsp; kalmanRoll.setRmeasure(0.01);<br>&nbsp; gyroRoll = accRoll;<br>&nbsp; timer = micros();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//计时&nbsp; //Timing<br>&nbsp; delay(1000);<br>&nbsp; getRoll();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //获得倾斜角&nbsp; //Get the pitch and roll angles<br>}<br><br>int outMax = 255;<br>int outMin = -255;<br>float lastInput = 0;<br>double ITerm = 0;<br>double kp = 100;<br>double ki = 2;<br>double kd = 0;<br><br>/*<br>&nbsp; &nbsp;计算PID输出函数 Compute PID output<br>*/<br>double Compute(double input) {<br>&nbsp; double error = Setpoint - input;<br>&nbsp; ITerm += (ki * error);<br>&nbsp; if (ITerm &gt; outMax) ITerm = outMax;<br>&nbsp; else if (ITerm &lt; outMin) ITerm = outMin;<br>&nbsp; double dInput = (input - lastInput);<br>&nbsp; double output = kp * error + ITerm + kd * dInput;<br>&nbsp; if (output &gt; outMax) output = outMax;<br>&nbsp; else if (output &lt; outMin) output = outMin;<br>&nbsp; lastInput = input;<br>&nbsp; return output;<br>}<br><br>/*<br>&nbsp; &nbsp;液晶屏显示欢迎界面函数 LCD welcome interface<br>*/<br>void initiateLCD() {<br>&nbsp; tft.initR(INITR_144GREENTAB);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//启动1.44寸液晶屏&nbsp; //Initiate the 1.44' LCD<br>&nbsp; tft.fillScreen(ST7735_WHITE);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//白色填充屏幕&nbsp; //Fill the LCD with white<br>&nbsp; clybot_r = tft.Color565(224, 58, 2);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //获得红、蓝两种颜色值&nbsp; //Get the red and blue colours<br>&nbsp; clybot_b = tft.Color565(1, 137, 149);<br>&nbsp; tft.drawBitmap (16, 64, 32, 60, Self_balancing);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //显示clybot C6图标&nbsp; //The clybot C6 icon<br>&nbsp; tft.drawBitmap (105, 85, 19, 19, Save);<br>&nbsp; for (int i = 0; i &lt; 20; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //屏幕上方两个方条动画&nbsp; //Animations of the two bars<br>&nbsp; &nbsp; tft.fillRect(0, 0, 6 * i, 25, clybot_b);<br>&nbsp; &nbsp; tft.fillRect(128 - 6 * i, 30, 6 * i, 25, clybot_r);<br>&nbsp; }<br>&nbsp; drawtext("Balancing", clybot_r, &amp;FreeSansBold9pt7b, 12, 17);&nbsp; &nbsp; &nbsp; //显示文字&nbsp; //Display characters<br>&nbsp; drawtext("clybot C6", ST7735_WHITE, &amp;FreeSansBold9pt7b, 32, 47);<br>&nbsp; drawtext("B Point", clybot_r, &amp;FreeSansBold9pt7b, 55, 75);<br>}<br><br>/*<br>&nbsp; &nbsp;最先执行的设置函数 //Setup function runs first<br>*/<br>void setup() {<br>&nbsp; initiateDevice();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//设备初始化函数&nbsp; //Device initialisation<br>&nbsp; initiateLCD();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //液晶屏欢迎界面显示函数&nbsp; //LCD welcome UI<br><br>&nbsp; int EEPROM_status;<br>&nbsp; EEPROM_status = EEPROM.read(0); //把EEPROM地址0状态读出&nbsp; //Read EEPROM address = 0<br>&nbsp; if (EEPROM_status == 88) {&nbsp; &nbsp; &nbsp; &nbsp;//如果状态为88，说明已经保存有平衡点角度&nbsp; //If data = 88, the balancing point has been stored previously<br>&nbsp; &nbsp; double EEPROM_RollInitial;<br>&nbsp; &nbsp; EEPROM.get(1, EEPROM_RollInitial);&nbsp; &nbsp; //把地址1上保存的平衡点角度读出&nbsp; //Get the initial roll angle from the address = 1<br>&nbsp; &nbsp; RollInitial = EEPROM_RollInitial;&nbsp; &nbsp; &nbsp;//把平衡点角度保存到RollInitial中&nbsp; //Pass the saved roll angle to RollInitial<br>&nbsp; &nbsp; rollDisplay(EEPROM_RollInitial);&nbsp; &nbsp; &nbsp; //显示平衡角度&nbsp; //Display roll angle<br>&nbsp; }<br>&nbsp; else&nbsp; calculateBias();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //如果之前没有保存平衡点角度，则计算初始偏移量函数&nbsp; //Calculate initial bias if not previously saved<br>}<br><br>int i = 0;<br>double aaa = 0;<br><br>void loop() {<br>&nbsp; runEvery(10) {<br>&nbsp; &nbsp; //检测按钮开关&nbsp; //Read buttons<br>&nbsp; &nbsp; Button_L_state = digitalRead(Button_L);<br>&nbsp; &nbsp; Button_R_state = digitalRead(Button_R);<br>&nbsp; &nbsp; if (Button_L_state == LOW) RollInitial += 0.02;<br>&nbsp; &nbsp; if (Button_R_state == LOW) RollInitial -= 0.02;<br>&nbsp; &nbsp; if ((Button_L_state == LOW) || (Button_R_state == LOW)) { &nbsp; //如果按钮按下，更新EEPROM&nbsp; //If button pressed, update the EEPROM<br>&nbsp; &nbsp; &nbsp; EEPROM.write(0, 88);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //向地址0写入平衡点保存标记88&nbsp; //Write the flag of 88 as the roll angle saved<br>&nbsp; &nbsp; &nbsp; EEPROM.put(1, RollInitial);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//向地址1保存平衡点角度&nbsp; //Save roll angle to address = 1<br>&nbsp; &nbsp; &nbsp; double EEPROM_RollInitial;<br>&nbsp; &nbsp; &nbsp; EEPROM.get(1, EEPROM_RollInitial);&nbsp; &nbsp; //从地址1读出数据传递给液晶屏显示&nbsp; //Read the roll angle from address = 1 to display on the LCD<br>&nbsp; &nbsp; &nbsp; rollDisplay(EEPROM_RollInitial);<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; getGyroValues();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //获得更新的传感器数据&nbsp; //Get updated sensor data<br>&nbsp; &nbsp; accRoll = (atan2(AcY, -AcZ) + PI) * RAD_TO_DEG; //获得倾斜角&nbsp; //Get the roll angle<br>&nbsp; &nbsp; if (accRoll &lt;= 360 &amp; accRoll &gt;= 180) accRoll = accRoll - 360;<br>&nbsp; &nbsp; gyroRateX = -((int)x - gyroBiasX) * .0105;<br>&nbsp; &nbsp; gyroRateY = -((int)y - gyroBiasY) * .0105;<br>&nbsp; &nbsp; gyroRateZ = ((int)z - gyroBiasZ) * .0105;<br><br>&nbsp; &nbsp; double leeeeel = gyroRateX * ((double)(micros() - timer) / 1000000);<br>&nbsp; &nbsp; gyroRoll += gyroRateX * ((double)(micros() - timer) / 1000000);<br>&nbsp; &nbsp; InputRoll = kalmanRoll.getAngle(accRoll, gyroRoll, (double)(micros() - timer) / 1000000);<br>&nbsp; &nbsp; timer = micros();<br>&nbsp; &nbsp; byte a = map(abs(Compute(InputRoll - RollInitial)), 0, 255, 0, 124);<br>&nbsp; &nbsp; aaa = 0.98 * (aaa + leeeeel) + 0.02 * (accRoll);<br>&nbsp; &nbsp; MotorControl(Compute(aaa - RollInitial));<br>&nbsp; }<br>}<br><br><br></div>]]></description>
         <enclosure url="" />
         <pubDate>2017-10-23 18:58:22 UTC</pubDate>
         <guid>https://padlet.com/chrisyang/c6/wish/199747224</guid>
      </item>
   </channel>
</rss>
