Arduino ESP32在两个内核中处理Web服务器和neopixels(带延迟)
我搜索答案已经有一段时间了,但还没有找到解决这个问题的方法。我有很多neopixel动画(目前有50个),这些都是用延迟编写的,这样可以使动画简单易读。缺点是你们都知道延迟。要重写的50个动画是一个地狱般的工作,所以我想避免这一点。我买了一个有两个内核的ESP32,所以我想我可以在一个内核上运行动画,在一个内核上运行Web服务器。以前我想在ESP8266上中断,但我测试了一下,比如在interrupt中无法进行通信或运行Web服务器。在ESP32上使用两个内核可以做到这一点吗?还是我遇到了与earlear相同的问题?程序的当前输出:我的Web服务器启动,按下按钮时会显示neopixel动画,但是我的Web服务器会一次又一次地重新启动。感谢您的帮助,提前谢谢 ps:在最坏的情况下,senario我必须重写我的动画,有人知道如何将3个for循环替换为非阻塞代码吗 在ESP32上运行的代码:Arduino ESP32在两个内核中处理Web服务器和neopixels(带延迟),arduino,webserver,esp8266,esp32,Arduino,Webserver,Esp8266,Esp32,我搜索答案已经有一段时间了,但还没有找到解决这个问题的方法。我有很多neopixel动画(目前有50个),这些都是用延迟编写的,这样可以使动画简单易读。缺点是你们都知道延迟。要重写的50个动画是一个地狱般的工作,所以我想避免这一点。我买了一个有两个内核的ESP32,所以我想我可以在一个内核上运行动画,在一个内核上运行Web服务器。以前我想在ESP8266上中断,但我测试了一下,比如在interrupt中无法进行通信或运行Web服务器。在ESP32上使用两个内核可以做到这一点吗?还是我遇到了与ea
TaskHandle_t Task1;
TaskHandle_t Task2;
#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 24
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
for(uint16_t i=0; i<NUM_LEDS; i++) {
setPixel(i, red, green, blue);
showStrip();
delay(SpeedDelay);
}
}
// *** REPLACE TO HERE ***
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
FastLED.show();
#endif
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
#endif
}
void setAll(byte red, byte green, byte blue) {
for(int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}
#include <WiFi.h>
const char* WIFI_NAME= "xxxxxxxxxx";
const char* WIFI_PASSWORD = "xxxxxxxxxx";
WiFiServer server(80);
String header;
// Auxiliar variables to store the current output state
String output5State = "off";
String output4State = "off";
// Assign output variables to GPIO pins
const int output5 = 2;
const int output4 = 4;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
String ledState = "off";
void setup() {
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// Set outputs to LOW
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
}
//Task1code: blinks an LED every 1000 ms
void Task1code( void * pvParameters ){
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
strip.begin();
strip.show(); // Initialize all pixels to 'off'
for(;;){
/*
digitalWrite(output5, HIGH);
delay(1000);
digitalWrite(output5, LOW);
delay(1000);*/
//Serial.print("state:" + ledState);
if(ledState == "on") {
//digitalWrite(output4, HIGH);
colorWipe(0x00,0xff,0x00, 50);
colorWipe(0x00,0x00,0x00, 50);
} else {
strip.clear();
strip.show();
}
}
}
//Task2code: blinks an LED every 700 ms
void Task2code( void * pvParameters ){
Serial.print("Connecting to ");
Serial.println(WIFI_NAME);
WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print("Trying to connect to Wifi Network");
}
Serial.println("");
Serial.println("Successfully connected to WiFi network");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
for(;;){
WiFiClient client = server.available();
if (client) {
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// turns the GPIOs on and off
if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
//digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
//digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
ledState = "on";
//digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
ledState = "off";
//digitalWrite(output4, LOW);
}
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP8266 Web Server</h1>");
// Display current state, and ON/OFF buttons for GPIO 5
client.println("<p>GPIO 5 - State " + output5State + "</p>");
// If the output5State is off, it displays the ON button
if (output5State=="off") {
client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Display current state, and ON/OFF buttons for GPIO 4
client.println("<p>GPIO 4 - State " + output4State + "</p>");
// If the output4State is off, it displays the ON button
if (output4State=="off") {
client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
}
void loop(){
}
TaskHandle\u t Task1;
任务句柄\u t Task2;
#包括”;
}否则{
client.println(“”);
}
//显示当前状态和GPIO 4的开/关按钮
client.println(“gpio4-State”+output4State+””;
//如果Output4状态为off,则显示ON按钮
如果(output4State==“关闭”){
client.println(“”);
}否则{
client.println(“”);
}
客户。println(“”);
//HTTP响应以另一个空行结束
client.println();
//打破while循环
打破
}否则{//如果有换行符,请清除currentLine
currentLine=“”;
}
}else如果(c!='\r'){//如果您得到的不是回车字符,而是其他字符,
currentLine+=c;//将其添加到currentLine的末尾
}
}
}
//清除header变量
标题=”;
//关闭连接
client.stop();
Serial.println(“客户端断开连接”);
Serial.println(“”);
}
}
}
void循环(){
}
具有三个for循环的动画:
void theaterChaseRainbow(int SpeedDelay) { /* for wheel watch higher in the code */
byte *c;
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (int i=0; i < NUM_LEDS; i=i+3) {
c = Wheels( (i+j) % 255);
setPixel(i+q, *c, *(c+1), *(c+2)); //turn every third pixel on
}
showStrip();
delay(SpeedDelay);
for (int i=0; i < NUM_LEDS; i=i+3) {
setPixel(i+q, 0,0,0); //turn every third pixel off
}
}
}
}
void theaterChaseRainbow(int SpeedDelay){/*对于代码中较高的车轮手表*/
字节*c;
对于(int j=0;j<256;j++){//循环控制盘中的所有256种颜色
对于(int q=0;q<3;q++){
对于(int i=0;i
在arduino,wifi设备在“2号”运行默认情况下为核心,不会与任务或信号量混淆。你不能同时做两件事。我已经将一些灯光效果转换为异步,与您所问的相同。基本思想是使循环计数器全局化,并终止for循环。用一个名为next()的函数替换内部循环体,该函数每次在loop()中调用。您必须在next()中处理变量增量和滚动,这是一些工作,但并不难。如果next()太频繁激发,您可能还必须提前返回,因为您没有延迟()…对于所示的chasers代码,您还需要一个mode全局布尔变量,您可以根据需要翻转该变量以仅运行前半部分或后半部分,通常是在增量溢出时。