Arduino Neopix系列问题

Arduino Neopix系列问题,arduino,uart,dma,neopixel,Arduino,Uart,Dma,Neopixel,我正在寻找一些帮助;了解DMA、串行、管理中断和阻塞代码 我有一个ESP32 DEVKITC v4,用于处理来自旋转编码器等硬件和wifi的用户输入。ESP32还负责驱动20x4 LCD显示菜单,供用户进行交互 然后我有了一个处理像素驱动的3.5版本。它负责生成像素帧,将其加载到缓冲区并输出信号。我正在运行一个修改版本的来控制我的TM1814 LED 目前我遇到的麻烦是ESP32和Teensy之间的通信。neopixel的代码需要阻塞,以便获得正确的LED驱动器IC的计时。虽然ESP有用于旋转编

我正在寻找一些帮助;了解DMA、串行、管理中断和阻塞代码

我有一个ESP32 DEVKITC v4,用于处理来自旋转编码器等硬件和wifi的用户输入。ESP32还负责驱动20x4 LCD显示菜单,供用户进行交互

然后我有了一个处理像素驱动的3.5版本。它负责生成像素帧,将其加载到缓冲区并输出信号。我正在运行一个修改版本的来控制我的TM1814 LED

目前我遇到的麻烦是ESP32和Teensy之间的通信。neopixel的代码需要阻塞,以便获得正确的LED驱动器IC的计时。虽然ESP有用于旋转编码器保持准确计数的中断,但这两种中断都会干扰串行通信。这是我到目前为止的测试代码,它是最终项目代码的精简版本,使识别问题变得简单,并帮助缓慢构建复杂性

电子稳定程序发送器

    #include <Rotary.h>

#define RTS_PIN 5

int previousArray;
int previousRGBW;

#define inPinA  35

//rotary acceleration variables
int rotaryTime;
volatile int counterA;
volatile int counterB;
byte enableAcceleration;
bool lockFlag = false;

Rotary rotaryA = Rotary(32, 33);

//teensy is expecting data <rgbwArrayToTeensy,rgbwToTeensy>
typedef struct ESPtransmit_t {
  char startMarker;
  int rgbwArrayToTeensy;
  char comma;
  int rgbwToTeensy;
  char endMarker;
};

typedef union Channel_Packet_t {
  ESPtransmit_t rgbwLED;
  byte ChannelPacket[sizeof(ESPtransmit_t)];
};

Channel_Packet_t blueOn;

void setup() {
  Serial.begin(9600);
  Serial2.begin(115200, SERIAL_8N1, 16, 17);

  while (!Serial);
  while (!Serial2);

  pinMode(RTS_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(RTS_PIN), Transmit_Data, RISING);
  attachInterrupt(digitalPinToInterrupt(32), rotateA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(33), rotateA, CHANGE);

}

void loop() {
  blueOn.rgbwLED = {'<', 2, ',', counterA, '>'};
}


void Transmit_Data() {
  noInterrupts();
  if (previousRGBW != blueOn.rgbwLED.rgbwToTeensy) {
    Serial2.write(blueOn.ChannelPacket, sizeof(ESPtransmit_t));
    Serial.println("send");
    previousRGBW = blueOn.rgbwLED.rgbwToTeensy;
  }
  interrupts();
}

void rotateA() {
  int speedMultiplier = 1;
  unsigned char result = rotaryA.process();
  if (lockFlag == false) {
    if (result == DIR_CW) {
      if (millis() - rotaryTime <= 10 && enableAcceleration == 0x01) {
        speedMultiplier = 7;

      }
      else if (digitalRead(inPinA) == HIGH) {
        speedMultiplier = 700;
      }
      counterA += speedMultiplier;
      rotaryTime = millis();
    }
    else if (result == DIR_CCW) {
      if (millis() - rotaryTime <= 10 && enableAcceleration == 0x01) {
        speedMultiplier = 7;

      }
      else if (digitalRead(inPinA) == HIGH) {
        speedMultiplier = 700;
      }
      counterA -= speedMultiplier;
      rotaryTime = millis();
    }
  }
}
#包括
#定义RTS_引脚5
int-previousArray;
int-previousRGBW;
#定义inPinA 35
//旋转加速度变量
int旋转时间;
挥发性int计数器A;
挥发性int计数器B;
字节启用加速;
bool lockFlag=false;
旋转旋转a=旋转(32,33);
//蒂恩西正在等待数据
类型定义结构ESPU\t{
char startMarker;
int RGBWARRATETENSY;
字符逗号;
int RGBwtoTensy;
字符结束标记;
};
typedef联合信道数据包{
ESPU t rgbwLED;
字节信道数据包[sizeof(ESPtransmit_t)];
};
信道分组;
无效设置(){
Serial.begin(9600);
序列2.开始(115200,序列号8N1,16,17);
而(!串行);
而(!Serial2);
引脚模式(RTS_引脚,输入);
连接中断(数字插针中断(RTS插针),传输数据,上升);
连接中断(数字插针中断(32)、旋转、更改);
连接中断(数字插针中断(33)、旋转、更改);
}
void循环(){
blueOn.rgbwLED={''};
}
无效传输_数据(){
无中断();
if(previousRGBW!=blueOn.rgbwLED.rgbwtoTensy){
Serial2.write(blueOn.ChannelPacket,sizeof(esptransfort));
Serial.println(“发送”);
previousRGBW=blueOn.rgbwLED.rgbwtoTensy;
}
中断();
}
void rotateA(){
int速度乘数=1;
unsigned char result=rotaryA.process();
if(lockFlag==false){
如果(结果==DIR\u CW){
if(millis()-rotaryTime
目前我遇到的麻烦是ESP32和Teensy之间的通信

如果串行链路的两端都有问题,则应尽量简化测试设置,以减少变量/未知数的数量。
使用ESP32传输数据,然后尝试使用终端或捕获程序(在PC上?)验证数据。
或者将屏蔽数据从PC传输到Teensy 3.5,然后分析响应


虽然这段代码大部分是有效的,但在快速旋转编码器时,我仍然会在传输中出错

我发现您的ESP\U发射器代码中有一个问题,即传输数据()过程:

void Transmit_Data() {
  noInterrupts();
  if (previousRGBW != blueOn.rgbwLED.rgbwToTeensy) {
    Serial2.write(blueOn.ChannelPacket, sizeof(ESPtransmit_t));
    Serial.println("send");
    previousRGBW = blueOn.rgbwLED.rgbwToTeensy;
  }
  interrupts();
}
在中断被禁用的情况下执行I/O请求是有问题的。
通常,您总是希望尽量减少禁用中断的时间

实际上我对Arduino一无所知,但是…
看起来
previousRGBW
和/或
blueOn
是必须保护的关键区域,可以在此代码段之外执行串行操作。
要保护
blueOn
只需复制一份
blueOn.ChannelPacket
用于串行传输。
以下内容应该是一种改进:

byte xmitPacket[sizeof(ESPtransmit_t)];

void Transmit_Data() {
  noInterrupts();
  if (previousRGBW != blueOn.rgbwLED.rgbwToTeensy) {
    memcpy(xmitPacket, blueOn.ChannelPacket, sizeof(ESPtransmit_t));
    previousRGBW = blueOn.rgbwLED.rgbwToTeensy;
    interrupts();

    Serial2.write(xmitPacket, sizeof(ESPtransmit_t));
    Serial.println("send");
  } else {
    interrupts();
  }
}

“Neopix的代码需要阻塞…”--您能解释一下这意味着什么吗?如果应用程序发出阻塞系统请求,那么这仅仅意味着程序将暂停,直到请求完成;同时系统可以自由执行其他任务。o如果设备有一定的定时要求,那么您可能不得不在操作之间引入延迟定量配给。如果你使用繁忙的等待,那么你已经占用了CPU,其他什么也做不了。这种延迟不是所谓的阻塞(至少不是我学的计算机科学)。很抱歉造成混淆,我使用的术语与Neopix代码作者使用的术语相同。当他们提到阻塞时,正如您所说,系统内置了延迟,用于对pin的高和低状态进行计时以发送数据。在整个发送时间内,中断也被完全禁用,以避免计时问题。嘿,Sawdust,谢谢您的建议ns我想我应该更清楚。我能够让两者之间的通信在一个基本的水平上工作,我可以从esp32发送blueOn,并在teesny 3.5上正确地接收和解析它。当我介绍
pixelsA.show()时当我遇到问题时,旋转编码器会打断我。我一定会采纳你的建议来保护blueOn。
byte xmitPacket[sizeof(ESPtransmit_t)];

void Transmit_Data() {
  noInterrupts();
  if (previousRGBW != blueOn.rgbwLED.rgbwToTeensy) {
    memcpy(xmitPacket, blueOn.ChannelPacket, sizeof(ESPtransmit_t));
    previousRGBW = blueOn.rgbwLED.rgbwToTeensy;
    interrupts();

    Serial2.write(xmitPacket, sizeof(ESPtransmit_t));
    Serial.println("send");
  } else {
    interrupts();
  }
}