学习记录:自平衡莱洛三角形v2(RGB版本)学习记录


来源:

v1版本::【开源】百元内可自制的自平衡莱洛三角形_哔哩哔哩_bilibili

v2版本: 【开源】自平衡莱洛三角形V2 | 我加了RGB性能翻倍_哔哩哔哩_bilibili


原作者开源链接:https://gitee.com/coll45/foc  

(本篇文章所有函数均为此开源网站下载函数)

说明:第一次接触Arduino和ESP32

关于此作品,作者在立创开源社区做了详细描述:

立创社区链接:v1:自平衡的莱洛三角_esp32_可充电_10*10版本 - 立创EDA开源硬件平台

                         v2:莱洛三角V2-esp32-无刷驱动EG2133 - 立创EDA开源硬件平台


参考文件:

灯哥开源FOC:【发布】不足百元!双路无刷电机驱动器 -灯哥双路无刷FOC驱动板正式开源!支持四足机器人!_哔哩哔哩_bilibili

simpleFOC库

KalmanFilter

FOC算法入门:FOC算法入门_梦如南伐的博客-CSDN博客_foc

爱转的光凌 CH32读取MPU6050姿态数据(卡尔曼滤波法)_哔哩哔哩_bilibili


由于之前分析了v1版本的基本代码,v2版本和v1版本基本差不多,此次只考虑v2版本的RGB和he触摸按键的实现。


RGB有关

依照作者所提供原理图,RGB接口接在了ESP32的IO16端口。状态指示灯接在IO4端口。RGB灯组使用的WS2812通过Adafruit_NeoPixel库控制。

(发表一下自己的小看法:RGB和touch的函数文件非常不规范,引以为戒!!不要这么操作!)

在RGB.h文件中调用了Adafruit_NeoPixel库并且宏定义WS2812控制端口

//RGB.h

#include <Adafruit_NeoPixel.h>

// Which pin on the Arduino is connected to the NeoPixels?
#define LED_PIN    16

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 21

在main函数中的setup配置了RGB

//RGB.h
unsigned char brightness = 30;

  //main

void setuo()
{
    .........................

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
                           //调用此函数显示,操作后必须调用显示
  strip.show();            // Turn OFF all pixels ASAP
                                   //设置亮度,在RGB.h中配置了
  strip.setBrightness(brightness); // Set BRIGHTNESS to about 1/5 (max = 255)

  colorWipe_delay(strip.Color(255, 106, 106),50); //R,G,B
  colorWipe_delay(strip.Color(0, 255, 255),50);
  colorWipe_delay(strip.Color(148, 0, 211),50);


    .........................
}

colorWipe_delay

//RGB.h

void colorWipe_delay(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

RGB.h文件下面包含了部分RGB灯效,通过判断触摸调用改变灯效。

//RGB.h

void strip1();
void strip2();
void strip3();
void rainbow1();
void rainbow2();
void pulse_rainbow1();
void rgb_off();
            ....................

触摸函数

触摸函数相关定义

//tourch.h

const int threshold_top = 40;   //触摸阈值
const int single_count[3] = {10,10,10};   //单击时间   实际时间为20*10 = 200ms
const int long_count[3] = {80,80,80};   //长按时间    实际时间为80*10 = 800ms
unsigned long touch_last_time;
int touch_count[3] = {0,0,0}; //持续触摸计数
int touch_touched[3] = {0,0,0};   //单击,长按判断  单击值为1,长按值为2  没点击为0
bool touch_STATE[3] = {1, 1, 1}; // 定义按键触发对象状态变量初始值为true默认开启 T2 T3 T4

int rgb_flag = 1;
int rgb_modle = 8;//有几种RGB效果就写几

触摸感应判断

//tourch.h

//在main中loop函数调用touchAttach(touchID,touchPin)
void touchAttach(int touchID, uint8_t touchPin) {
  int touchread = touchRead(touchPin);        //触摸返回函数

  if ( touchread <= threshold_top ) { //达到触发值的计数
    //delay(38);  // 0.038秒
    touch_count[touchID]++; //持续触摸计数
  } 
  //没有触摸时才进入触摸类型判断函数  
  else
  {
  if ( touch_count[touchID] >= single_count[touchID] && 
                                    touch_count[touchID] < long_count[touchID])
    touch_touched[touchID] = 1;//持续触摸时间达到单击
  else if(touch_count[touchID] >= long_count[touchID])
    touch_touched[touchID] = 2;
  else
      touch_touched[touchID]= 0;
  touch_count[touchID] = 0;  //持续触摸计数清零
  }
}

loop函数中,通过触摸改变RGB灯效

//main

void loop()
{
    .........................
    
  // 触摸效果以及RGB灯效
  unsigned long currentMillis = millis();  //获取开机后运行的时间长度ms
  if(currentMillis - voltage_last_time >=1000)
  {
    voltage_last_time = currentMillis;
    voltage_detection();        //有关电池电压检测加输出结果的函数!
  }
  if(currentMillis - touch_last_time >= 10)  //  Check for expired time
  {       
    touch_last_time = currentMillis;                            //  Run current frame
  
     /*******************************************************
     ESP32LED闪烁
     功能:实现触摸按键按一下改变LED得状态
     引脚:
     T0:GPIO 4
     T1:GPIO 0
     T2:GPIO 2
     T3:GPIO 15
     T4:GPIO 13
     T5:GPIO 12
     T6:GPIO 14
     T7:GPIO 27
     T8:GPIO 33
     T9:GPIO 32
     arduino 也内置有相应的语法:touchRead(Touch Pin *);
     https://img-blog.csdnimg.cn/d117f52b602e45f78ed63ca82a610b32.png
     *******************************************************/
     touchAttach(0,T2);
     touchAttach(1,T3);
     touchAttach(2,T4);
     int i;
     for(i = 0;i<3;i++)
     {
       if(touch_STATE[i]&&touch_touched[i]) //开启检测&&有按下
        {
            if(touch_touched[i] == 1)
            {
              single_event(i);  //触摸单击函数
            }
            else
              long_event(i);    //触摸长按函数
        }
     }
  }


    .........................

}

按键模式处理函数

//main

void loop()
{
    .........................

//  Update current time  更新RGB效果

  //就是隔一段时间运行一次
  if(currentMillis - pixelPrevious >= pixelInterval) //  Check for expired time
  {        
    pixelPrevious = currentMillis;                            //  Run current frame
    switch(rgb_flag)
    {
    case 0 :
      rgb_off();
      break;
    case 1 :
      if(motor.shaft_velocity>0)
      {
        pixelInterval = 150 - motor.shaft_velocity;
        strip2();
      }
      else
      {
        pixelInterval = 150 + motor.shaft_velocity;
        strip3();  
      }
      break;
    case 2 :
      pixelInterval = 100;
      strip2();
      break;
    case 3 :
      pixelInterval = 100;
      strip3();  
      break;
    case 4 :
      strip1();
      break;
    case 5 :
      rainbow1();  
      break;
    case 6 :
      rainbow2();  
      break;
    case 7 :
      pulse_rainbow1();  
      break;
    }
  }

    .........................

}

触摸单机函数

//main


//触摸单击函数处理
void single_event(int touchID)
{
  switch(touchID){
    case 0  :            //亮度减
       if(brightness<=15) //亮度
        brightness = 15; 
       brightness-=15;
       EEPROM.writeUChar(28, brightness);  EEPROM.commit();
       strip.setBrightness(brightness); // Set BRIGHTNESS to about 1/5 (max = 255)
       break; 
    case 1  :           //亮度加
      if(brightness>=240)
            brightness = 240;
       brightness+=15;      
       EEPROM.writeUChar(28, brightness);  EEPROM.commit();
       strip.setBrightness(brightness); // Set BRIGHTNESS to about 1/5 (max = 255)
       break; 
    case 2 :            //RGB开关
       if(rgb_flag)
          rgb_flag = 0;
       else
          rgb_flag = EEPROM.readUChar(32);
       break; 
  }  
}

触摸长按函数

//main


//触摸长按函数处理
void long_event(int touchID)
{
  switch(touchID){
    case 0  : //长按投币    //切换RGB
       if(rgb_flag == 0)
          rgb_flag = rgb_modle;
       rgb_flag--;
       strip.setBrightness(brightness); // Set BRIGHTNESS to about 1/5 (max = 255)
       EEPROM.writeUChar(32, rgb_flag);  EEPROM.commit();
       break; 
    case 1  :  //长按收藏    //切换RGB
       rgb_flag++;
       if(rgb_flag>=rgb_modle)
          rgb_flag = 0;
       strip.setBrightness(brightness); // Set BRIGHTNESS to about 1/5 (max = 255)
       EEPROM.writeUChar(32, rgb_flag);  EEPROM.commit();
       break; 
    case 2 : //长按点赞
       if(wifi_on_off)
        {
           motor.enable();
          WiFi.disconnect();
          WiFi.mode(WIFI_OFF);
          Serial.println("WIFI_OFF");
        }
       else
       {
        motor.disable();
        AutoWifiConfig();//打开wifi
        Serial.println("WIFI_ON");
       }
       wifi_on_off = !wifi_on_off;
       Motor_enable_flag = !Motor_enable_flag;
       break; 
  }  
}

在setup函数中,写了brighyness、rgb_flag到EEPROM

   //main  

      EEPROM.writeUChar(28,brightness); delay(10);EEPROM.commit();
      EEPROM.writeUChar(32,rgb_flag); delay(10);EEPROM.commit();

电池检测的函数

这一部分比较简单




void voltage_detection()
{
  #if defined(BAT_VOLTAGE_SENSE_PIN)  //电池电压检测
  bat_voltage = return_voltage_value(BAT_VOLTAGE_SENSE_PIN);
  //driver.voltage_power_supply = bat_voltage;
  //Serial.println(driver.voltage_power_supply);
  if (bat_voltage < min_voltage && !battery_low)
  {
    battery_low = 1;
    Serial.print(driver.voltage_power_supply);
    Serial.println("V ");
    Serial.print(bat_voltage);
    Serial.println("V battery_low!!");
    while (battery_low)
    {
      rgb_off();
      motor.disable();

      bat_voltage = return_voltage_value(BAT_VOLTAGE_SENSE_PIN);
      if (bat_voltage >= (min_voltage + 0.5)) {
        Serial.print(driver.voltage_power_supply);
        Serial.println("V");
        Serial.print(bat_voltage);
        Serial.println("V battery ok");
        digitalWrite(ACTIVE_PIN, 0);  //电池电压恢复则常亮,需reset重启
        //battery_low = 0;
      } else {  //电池电压低闪灯
        if (millis() % 500 < 250)
          digitalWrite(ACTIVE_PIN, 0);
        else
          digitalWrite(ACTIVE_PIN, 1);
      }
    }
  }
#endif
}

return_voltage_value(int pin_on)

double return_voltage_value(int pin_no)
{
  double tmp;
  double ADCVoltage;
  double inputVoltage;
  analogSetPinAttenuation(pin_no, ADC_6db);  //制定引脚输入衰减

  for (int i = 0; i < 20; i++)
  {
                    //默认12位分辨率
    ADCVoltage = analogReadMilliVolts(pin_no) / 1000.0;
    inputVoltage = (ADCVoltage * R1_VOLTAGE) / R2_VOLTAGE;

    tmp = tmp + inputVoltage + ADCVoltage; 
                                // formula for calculating voltage in i.e. GND
  }
  inputVoltage = tmp / 20;
  if(inputVoltage!=0)
    inputVoltage = inputVoltage + 0.001;
/*

  for (int i = 0; i < 20; i++)
  {
    tmp = tmp + analogRead(pin_no);
  }
  tmp = tmp / 20;

  ADCVoltage = ((tmp * 3.3) / 4095.0) + 0.165;
  inputVoltage = ADCVoltage / (R2_VOLTAGE / (R1_VOLTAGE + R2_VOLTAGE)); 
                    // formula for calculating voltage in i.e. GND
*/

  return inputVoltage;
}

有关OTA的问题没有探讨

最后、原作者代码很乱、引以为戒。

编译成功了!重装了好几个库,不知道是不是我的版本不对~

项目v1,v2的代码和实现方法有了简要的理解,嗯~ ~ ~ 对我的工作还是比较满意~硬件电路比较简单啦~ 看看作者给的原理图基本上就清晰啦!!总之,这个项目就这样吧,如果以后想继续研究SimpleFOC和Kalman的原理和代码实现的时候,再更新这个专栏吧~ ~ ~  !

加油学习~ 多看项目~ 多学原理~

一定要多看原理,不要单纯复刻,烧录谁不会

再次感谢大佬提供的开源项目!!!

最后附上大佬的B站链接:455555菌的个人空间_哔哩哔哩_Bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值