Mini四轴自动控制(五) ESP8266-12F SPI通信,电机PWM频率自定义-Arduino中文社区 - Powered by Discuz! Archiver

zxldwlsj 发表于 2018-11-27 19:59

Mini四轴自动控制(五) ESP8266-12F SPI通信,电机PWM频率自定义

本帖最后由 zxldwlsj 于 2018-12-1 08:35 编辑

好久没更新了,今天给大家带来了满满的干货:


[*]Arduino Leonardo和ESP8266 SPI接口通信;
[*]四个电机PWM频率自定义设置。因为用analogWrite频率会很低,对空心杯不合适(这里涉及多个定时器的设置,以后会给出详细文档介绍);
[*]如何将浮点数据和字节数据相互转化。因为spi是一个字节一个字节传数据的,而我们的数据又是小数,所以为了传输数据,要将小数转为字节,同时接受到字节数据,我们还得转为小数用于我们的控制器设计。



废话不多说,直接上代码。代码我就不做具体解释了,萌新看不懂的可以留言,我会回复的。定时器设置部分(带pwm字眼的)可以先不看,等我下回分解。

下面这是写到ESP8266里面的,从机模式。注意由于这里的代码显示有问题,大家要仔细检查#include <ESP8266WiFi.h>
#include "SPISlave.h"

uint8_t buf_RecFromWiFi = {0};
uint8_t buf_SendToWiFi = {0};
const char *ssid   = "Quanser_UVS";
const char *password = "UVS_wifi";
const char *host = "192.168.2.10";
const int tcpPort = 18005;
IPAddress staticIP(192,168,2,66);
IPAddress gateway(192,168,2,10);
IPAddress subnet(255,255,255,0);
WiFiClient client;

void setup()
{
// Serial.begin(115200);
WiFi.begin(ssid, password);
WiFi.config(staticIP, gateway, subnet);
while (WiFi.status() != WL_CONNECTED)
    {
      delay(100);
   }
SPISlave.begin();
}

void loop()
{
while (!client.connected())
    {
      if (!client.connect(host, tcpPort))
      {
            delay(50);
      }
    }   
/**** read motor data from wifi and send them to master ****/
   if (client.available())
   {
      for(int i=0;i<16;i++)
      {
      buf_RecFromWiFi = client.read();
       }
      for(int j=16;j<32;j++)
      {
      buf_RecFromWiFi = 0;
       }
       SPISlave.setData(buf_RecFromWiFi,32);
   }
   
   // delay(2);   
/**** read data from master and send them to wifi ****/
   SPISlave.onData([](uint8_t * buf_send, size_t len) {
      for(int j=0;j<32;j++)
      {
         buf_SendToWiFi =buf_send;
      }
      });
   for(int j=0;j<32;j++)
   {
      client.write(buf_SendToWiFi);
   }               
}

下面写到arduino开发板里面,注意由于这里的代码显示有问题,大家要仔细检查



#include <SPI.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
MPU6050 mpu;

float dt;
int16_t ax, ay, az, gx, gy, gz;
uint32_t timer;
float MOTOR1 = 0, MOTOR2 = 0, MOTOR3 = 0, MOTOR4 = 0;
int moto1 = 0, moto2 = 0, moto3 = 0, moto4 = 0;
uint8_t buf_receive = {0};
uint8_t buf_send = {0};

union Float6ToByte24
{
float Float;
uint8_t Byte;
};
union Float4ToByte16
{
float Float;
uint8_t Byte;
};
union Float1ToByte4
{
float Float;
uint8_t Byte;
};
Float6ToByte24 gyo_union;
Float4ToByte16 motor_union;
Float1ToByte4 dt_union, motor_add_union;
class ESPSafeMaster {
private:
    uint8_t _ss_pin;
    void _pulseSS() {
      digitalWrite(_ss_pin, HIGH);
      delayMicroseconds(5);
      digitalWrite(_ss_pin, LOW);
    }
public:
    ESPSafeMaster(uint8_t pin): _ss_pin(pin) {}
    void begin() {
      pinMode(_ss_pin, OUTPUT);
      _pulseSS();
    }

    uint32_t readStatus() {
      _pulseSS();
      SPI.transfer(0x04);
      uint32_t status = (SPI.transfer(0) | ((uint32_t)(SPI.transfer(0)) << 8) | ((uint32_t)(SPI.transfer(0)) << 16) | ((uint32_t)(SPI.transfer(0)) << 24));
      _pulseSS();
      return status;
    }

    void writeStatus(uint32_t status) {
      _pulseSS();
      SPI.transfer(0x01);
      SPI.transfer(status & 0xFF);
      SPI.transfer((status >> 8) & 0xFF);
      SPI.transfer((status >> 16) & 0xFF);
      SPI.transfer((status >> 24) & 0xFF);
      _pulseSS();
    }

    void readData(uint8_t * data) {
      // _pulseSS();
      SPI.transfer(0x03);
      SPI.transfer(0x00);
      for (uint8_t i = 0; i < 32; i++) {
      data = SPI.transfer(0);
      }
      // _pulseSS();
    }

    void writeData(uint8_t * data, size_t len) {
      uint8_t i = 0;
      //_pulseSS();
      SPI.transfer(0x02);
      SPI.transfer(0x00);
      while (len-- && i < 32) {
      SPI.transfer(data);
      }
      while (i++ < 32) {
      SPI.transfer(0);
      }
      // _pulseSS();
    }
};
ESPSafeMaster esp(8);

void pwm5_9_10configure(int mode)
{
// TCCR1A configuration
//00 : Channel A disabled D9
//00 : Channel B disabled D10
//00 : Channel C disabled D11
//01 : Fast PWM 8 bit
TCCR1A = 1;
TCCR3A = 1;

// TCCR1B configuration
// Clock mode and Fast PWM 8 bit
TCCR1B = mode | 0x08;
TCCR3B = mode | 0x08;

// TCCR1C configuration
TCCR1C = 0;
TCCR3C = 0;
}
void pwm6configure(int mode)
{
// TCCR4A configuration
TCCR4A = 0;
// TCCR4B configuration
TCCR4B = mode;
// TCCR4C configuration
TCCR4C = 0;
// TCCR4D configuration
TCCR4D = 0;
// PLL Configuration
// Use 96MHz / 1.5 = 64MHz
PLLFRQ = (PLLFRQ & 0xCF) | 0x20;
// PLLFRQ=(PLLFRQ&0xCF)|0x10;// Will double all frequencies

// Terminal count for Timer 4 PWM
OCR4C = 255;
}
void pwmSet5(int value)
{
OCR3A = value; // Set PWM value
//DDRB|=1<<5;    // Set Output Mode B5
TCCR3A |= 0x80; // Activate channel
}
void pwmSet9(int value)
{
OCR1A = value; // Set PWM value
//DDRB|=1<<5;    // Set Output Mode B5
TCCR1A |= 0x80; // Activate channel
}
void pwmSet10(int value)
{
OCR1B = value; // Set PWM value
//DDRB|=1<<6;    // Set Output Mode B6
TCCR1A |= 0x20; // Set PWM value
}
void pwmSet6(int value)
{
OCR4D = value; // Set PWM value
//DDRD|=1<<7;    // Set Output Mode D7
TCCR4C |= 0x09; // Activate channel D
}
void setup()
{
//Serial.begin(115200);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pwm5_9_10configure(1);//16M/256/1=62500Hz
// pwm5_9_10configure(3);//16M/256/64=976Hz
pwm6configure(4);//64M/256/4=62500Hz
// pwm6configure(9);//64M/256/256=976Hz
SPI.begin();
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
mpu.initialize();
esp.begin();
delay(500);
}

void loop()
{
dt = (float)(micros() - timer) / 1000000; // Calculate delta time
timer = micros();
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);   //IIC获取MPU6050六轴数据 ax ay az gx gy gz
gyo_union.Float = ax;
gyo_union.Float = ay;
gyo_union.Float = az;
gyo_union.Float = gx;
gyo_union.Float = gy;
gyo_union.Float = gz;
motor_add_union.Float=MOTOR1+MOTOR2+MOTOR3+MOTOR4;
// motor_add_union.Float = 0;
dt_union.Float = dt;

for (int i = 0; i < 24; i++)
{
    buf_send = gyo_union.Byte;
}
for (int i = 24; i < 28; i++)
{
    buf_send =motor_add_union.Byte;
}
for (int i = 28; i < 32; i++)
{
    buf_send =dt_union.Byte;
}

esp.writeData(buf_send, 32); //write data (32 bytes)
delay(1);
esp.readData(buf_receive); //read data (16 bytes)

for (int i = 0; i < 16; i++)
{
    motor_union.Byte = buf_receive;
}
MOTOR1 = motor_union.Float;
MOTOR2 = motor_union.Float;
MOTOR3 = motor_union.Float;
MOTOR4 = motor_union.Float;

moto1 = (int) MOTOR1;
moto2 = (int) MOTOR2;
moto3 = (int) MOTOR3;
moto4 = (int) MOTOR4;

//Serial.println("data");
//Serial.println(MOTOR1);
//Serial.println(MOTOR2);
//Serial.println(MOTOR3);
//Serial.println(MOTOR4);
      if(moto1>=0&&moto1<=255)
      {pwmSet5(moto1);}
       else
      {pwmSet5(0);}
      if(moto2>=0&&moto2<=255)
      {pwmSet6(moto2);}
      else
      {pwmSet6(0);}
      if(moto3>=0&&moto3<=255)
      {pwmSet9(moto3);}
      else
      {pwmSet9(0);}
      if(moto4>=0&&moto4<=255)
      {pwmSet10(moto4);}
      else
      {pwmSet10(0);}
}

最后提一下,控制算法没在arduino里面,而在上位机电脑里面,用matlab/simulink模块搭建的,上位机只用算出四个电机的pwm,通过路由器发送给esp8266即可,同时,arduino还得把陀螺仪数据,pwm求和,采样时间,这三类数据一共32byte通过8266传回电脑。这样就形成了闭环控制系统,读者可以去我项目第二章查看相关原理图。







sxtylzx 发表于 2019-4-25 16:29

我是新来的

0526468 发表于 2020-8-8 21:25

楼主不干了吗,一年多不更新了

zxldwlsj 发表于 2020-9-6 15:17

0526468 发表于 2020-8-8 21:25
楼主不干了吗,一年多不更新了

干完了 完美收工 哈哈 以后再开一贴

1052196225 发表于 2020-10-28 21:52

楼主厉害

Larry01 发表于 2021-4-11 13:25

半年了,没动静啊
页: [1]
查看完整版本: Mini四轴自动控制(五) ESP8266-12F SPI通信,电机PWM频率自定义