从ESP32蓝牙库生成的回调访问地图/矢量时,空键/值的问题 硬件:回溯已解码: Arduino Sketch NodeESP.h NodeESP.cpp 示例程序

如何解决从ESP32蓝牙库生成的回调访问地图/矢量时,空键/值的问题 硬件:回溯已解码: Arduino Sketch NodeESP.h NodeESP.cpp 示例程序

我试图每次ESP32节点收到某个字符时都触发一个函数。我可以接收数据并从我制作的数据包结构中解析出char。我将所有操作注册在类型的映射中,其中

typedef void (*callback_function)(void);

这个想法是我将所有字符链接到它们各自的功能。然后,我可以解析出一个char并找到指向我想轻松触发的函数的指针。唯一的缺点是我必须保留对全局对象的引用,才能从bluetooth_callback内部访问此映射。我已经进行了将近2天的测试,并且编写了一些没有espressif API的示例代码。就我自己而言,我的代码似乎可以正常运行,并且也可以在ESP32上运行。但是,如果我在espressif API注册之后让bluetooth_callback被调用(即,让真正的蓝牙事件触发回调),则该行为变得不确定。映射的大小与我添加到其中的对的数量仍然正确,但是所有的值和键均为null或未定义,并且如果我尝试访问它们,则会收到Guru Meditation Error。我一直在尝试解决这个问题很多,这种行为对我来说很奇怪。如果我手动调用回调函数,那么一切似乎都可以正常工作,但是如果我让它被蓝牙事件调用,则会出现不确定的行为并崩溃。我不确定我是不是在c ++上做错了事,还是这是esp32特有的问题。我可能犯了一个愚蠢的错误。我已经附加了我的Arduino脚本,正在处理的库的头文件和cpp文件,以及一个示例应用程序,该应用程序应显示我的工作意图。谢谢您的帮助。

硬件:

主板:ESP32开发模块(Sparkfun ESP32东西)

核心安装版本:1.0.3

IDE名称:Arduino IDE

闪光频率:40Mhz

启用PSRAM:否

上传速度:115200

计算机操作系统:Windows 10

回溯

Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x400014e8  PS      : 0x00060430  A0      : 0x800d2410  A1      : 0x3ffcf1a0  
A2      : 0x000000fe  A3      : 0x000000fc  A4      : 0x000000ff  A5      : 0x0000ff00  
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x800d2228  A9      : 0x3ffcf170  
A10     : 0x3ffbed90  A11     : 0x3f40148b  A12     : 0x3f40148b  A13     : 0x0000ff00  
A14     : 0x00ff0000  A15     : 0xff000000  SAR     : 0x00000010  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x000000fc  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xfffffffb  

Backtrace: 0x400014e8:0x3ffcf1a0 0x400d240d:0x3ffcf1b0 0x400d242d:0x3ffcf1d0 0x400d14a2:0x3ffcf1f0 0x400d1501:0x3ffcf210 0x400df881:0x3ffcf230 0x400d8362:0x3ffcf280 0x4008d83d:0x3ffcf2b0

已解码:

PC:0x400014e8 EXCVADDR:0x000000fc

Decoding stack results
0x400d240d: Print::write(char const*) at C:\Users\Jake Booth\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.3\cores\esp32/Print.h line 66
0x400d242d: Print::print(char const*) at C:\Users\Jake Booth\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.3\cores\esp32\Print.cpp line 89
0x400d14a2: NodeESP::act_message(char*) at C:\Users\Jake Booth\Documents\Arduino\libraries\NodeESP\NodeESP.cpp line 336
0x400d1501: NodeESP::bluetooth_callback(esp_spp_cb_event_t,esp_spp_cb_param_t*) at C:\Users\Jake Booth\Documents\Arduino\libraries\NodeESP\NodeESP.cpp line 176
0x400df881: btc_spp_cb_handler at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c line 152
0x400d8362: btc_task at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/bt/bluedroid/btc/core/btc_task.c line 110
0x4008d83d: vPortTaskWrapper at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/port.c line 143

我在下面突出显示了第336行,以方便地显示它是哪一个。

Arduino Sketch

#include "NodeESP.h"

#define LED_PIN 5

#define TOGGLE_LED_CHAR 'l'
#define TURN_ON_LED_CHAR 'p'

void setup() {
  // put your setup code here,to run once:
  Serial.begin(115200);
  
  pinMode(LED_PIN,OUTPUT);

  char l = TOGGLE_LED_CHAR;
  char p = TURN_ON_LED_CHAR;

  esp_spp_cb_param_t ex_param;
  ex_param.data_ind.data = (uint8_t*)l;
  ex_param.data_ind.len = 1;
  //ex_param_ptr = *ex_param;

  NodeESP node_esp;
  node_esp.add_func(&p,toggle_LED);
  node_esp.add_func(&l,turn_on_LED);
  node_esp.begin("TEST_1");
//Just calling it manually works,but when the espressif API calls it I get undefined behaviour.
//  NodeESP::bluetooth_callback(ESP_SPP_DATA_IND_EVT,&ex_param);
}

void toggle_LED()
{
  Serial.println("toggle_LED()");
}

void turn_on_LED()
{
  Serial.println("turn_on_LED()");
}

void loop() {
  // put your main code here,to run repeatedly:
  while(1)
  {
    vTaskDelay(100 / portTICK_PERIOD_MS);
  }
}

NodeESP.h

/*
  NodeESP.cpp - Library for automatically connecting to and using esp32 microcontrollers
  Created by Jacob Booth 11/9/2020
*/

#ifndef NodeESP_h
#define NodeESP_h

#include "Arduino.h"

#include <ESPmDNS.h>
#include <WiFi.h>
#include <map>

#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_spp_api.h"
#include "esp_gap_bt_api.h"

//---Define buffer constants--------------------------
#define RCV_BUF_SIZE 128
#define TX_BUF_SIZE 256

//---Define communication constants-------------------
#define RFCOMM_CHANNEL 1
#define RFCOMM_MAX_FRAME_SIZE 0xffff

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! please run 'make menuconfig' to enable it
#endif

class NodeESP
{
  public:
    //Constructor
    NodeESP();
    
    //Begin
    bool begin(const char *_name);

    //Typedef
    typedef void (*callback_function)(void);

    //Variables
    uint32_t bt_handle;
    const char *_name;
    std::map<char*,callback_function> funcs;
    
    char rx_buf[RCV_BUF_SIZE];
    char tx_buf[RCV_BUF_SIZE];
    WiFiServer server;
    WiFiClient client;
    
    //Generic
    void add_func(char* command,callback_function func);
    void act_message(char* trigger);

    //Bluetooth
    void bluetooth_write(char *buf,int len);
    bool bluetooth_spp_init();
    bool bluetooth_init(const char *deviceName);
    
    static char parse_data(uint8_t *rcvd,uint16_t len);
    static void bluetooth_callback(esp_spp_cb_event_t event,esp_spp_cb_param_t *param);

    String toString(const IPAddress & address);
  private:
};
#endif

NodeESP.cpp

/*
  NodeESP.cpp - Library for automatically connecting to and using esp32 microcontrollers
  Created by Jacob Booth 11/9/2020
*/

#include "Arduino.h"

#include <ESPmDNS.h>
#include <WiFi.h>
#include <map>

#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_spp_api.h"
#include "esp_gap_bt_api.h"

#include "NodeESP.h"

using namespace std;

//---State Machine Variables---
//State enum that helps the state machine track its way through 
//connecting to wifi.
enum state_t {
  UNDEFINED,DISCONNECTED,WIFI_CON,SERVER_CON
};

enum comm_t {
  s,NONE,WIFI,BLUETOOTH,q
};

//The current communication protocol we are using
comm_t cur_comm = s;

//The current state
state_t cur_state = UNDEFINED;


char tx_buf[TX_BUF_SIZE];
char rx_buf[RCV_BUF_SIZE];

//---Wifi
WiFiServer server(0);
WiFiClient client;

//---Bluetooth
uint32_t bt_handle;

void* example_obj;

//---Main Init--------------------------------------------------------
NodeESP::NodeESP()
{
  this->_name = "default";
  example_obj = (void*)this;
}

bool NodeESP::begin(const char *_name)
{
  this->_name = _name;
  
  //For testing set the current communication method to bluetooth
  cur_comm = BLUETOOTH;
    
  switch (cur_comm)
  {
    case UNDEFINED:
      return false;
      break;
      
    case NONE:
      return false;
      break;
      
    case WIFI:
      return true;
      break;
      
    case BLUETOOTH:
      if (!this->bluetooth_init(_name))
      {
        return false;
      }
      break;
  }
  return true;
}

//---Bluetooth Functions--------------------------------
bool NodeESP::bluetooth_init(const char *deviceName)
{
  //Start Bluetooth
  if (!btStart()) 
  {
    return false;
  }
  
  //Start BlueDroid (bluetooth stack)
  if (esp_bluedroid_init()!= ESP_OK) 
  {
    return false;
  }
  
  //Enable BlueDroid
  if (esp_bluedroid_enable()!= ESP_OK) 
  {
    return false;
  }
  
  //Set device name
  esp_bt_dev_set_device_name(deviceName);
  
  //Set sannable and discoverable
  esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
  
  //Init spp server
  if (!this->bluetooth_spp_init())
  {
    return false;
  }
  //Set send bytes to the correct callback
  //send_bytes = write_bluetooth;
  return true;
}

bool NodeESP::bluetooth_spp_init()
{
  if (esp_spp_register_callback(&bluetooth_callback) != ESP_OK)
  {
    return false;
  }
  
  if (esp_spp_init(ESP_SPP_MODE_CB) != ESP_OK)
  {
    return false;
  }

  if (esp_spp_start_srv(ESP_SPP_SEC_NONE,ESP_SPP_ROLE_SLAVE,1,"") != ESP_OK)
  {
    return false;
  }
  return true;
}

void NodeESP::bluetooth_write(char *buf,int len)
{
  esp_spp_write(bt_handle,len,(uint8_t*)buf);
}

void NodeESP::bluetooth_callback(esp_spp_cb_event_t event,esp_spp_cb_param_t *param)
{
  switch (event)
  {
    case ESP_SPP_SRV_OPEN_EVT:
    {
      NodeESP* self = (NodeESP*) example_obj;
      self->bt_handle = param->srv_open.handle;
      break;
    }  
    case ESP_SPP_CL_INIT_EVT:
      esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_NONE);
      break;
    case ESP_SPP_OPEN_EVT:
      break;
    case ESP_SPP_DATA_IND_EVT:
    {
      NodeESP* self = (NodeESP*) example_obj;
      //char trig = self->parse_data(param->data_ind.data,param->data_ind.len);
      self->act_message((char*)param->data_ind.data);
      break;
    }
    case ESP_SPP_CLOSE_EVT:
      esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
    case ESP_SPP_WRITE_EVT:
      break;
    case ESP_SPP_CONG_EVT:
      break;
  }
  return;
}

//---Parsing functions-------------------------------
//TODO: Add circular buffer
char NodeESP::parse_data(uint8_t *rcvd,uint16_t len)
{
  
  char body_buf[RCV_BUF_SIZE];
  uint8_t len_buf[2];
  uint8_t rcvd_bytes = 0;
  uint8_t recive_stage = 0;

  uint16_t calc_len = 0;
  
  //Loop through each char recieved
  for (uint16_t i = 0; i < len; i++)
  {
    uint8_t cur_char = rcvd[i];
    rcvd_bytes++;
 
    //If we haven't recieved the length or body
    //And we recieve a start delim
    if (recive_stage == 0 && cur_char == 0x7E)
    {
      //We are ready to read the length of the message (next 2 bytes)
      recive_stage = 1;
      rcvd_bytes = 0;
    } 
    else if (recive_stage == 1)//If we are recieving the length
    {      
      //Next two bytes get stored in the length buffer
      len_buf[rcvd_bytes - 1] = cur_char;
            
      //If we have recieved the 2 length bytes
      if (rcvd_bytes == 2)
      {
        //Decode the length
        calc_len = ((uint16_t)len_buf[0]) << 8 | (uint16_t)len_buf[1];
                
        //Ready to recieve the body
        recive_stage = 2;
        rcvd_bytes = 0;
      }
    } 
    else if (recive_stage == 2)//If we are recieving the body
    {
      //Store the recieved bytes
      body_buf[rcvd_bytes - 1] = cur_char;

      if (rcvd_bytes == calc_len)
      {
        //Reset
        rcvd_bytes = 0;
        recive_stage = 0;

        return(cur_char);
      }
    }
  }
  return '/';
}

void NodeESP::add_func(char* command,callback_function func)
{
  Serial.println("Added new callback...");
  std::pair<char*,callback_function>* new_pair = new std::pair<char*,callback_function>(command,func);
  this->funcs.insert(*new_pair);
}

void NodeESP::act_message(char* trigger)
{  
  Serial.println("[act message]");
  Serial.print("funcs.size() = ");
  Serial.print(this->funcs.size()); //Always returns the correct size all of the time
  Serial.println("");
  
  for  (std::map<char*,callback_function>::iterator it = this->funcs.begin();
        it != this->funcs.end(); 
        ++it)
  {
    Serial.print("funcs[i].first = ");
    Serial.print(it->first); //Line 336,accessing the first element of the iterator
    Serial.println("");       //This works properly when I don't call the function through the callback.
    if (trigger == it->first)
    {
        (it->second)();
    }
  }
}


String NodeESP::toString(const IPAddress & address)
{
  return String(address[0]) + "." + address[1] + "." + address[2] + "." + address[3];
}

示例程序

这是一个示例程序,显示了我想要发生的事情并且可以正常运行。

// Example program
#include <iostream>
#include <string>
#include <map>
//Global object to access the instance from within static function

using namespace std;


class example
{
  public:

    example();
    void begin();
    typedef void (*callback_function)(void);
    std::map<char,callback_function> funcs;

    void add_func(char command,callback_function func);
    void do_something(char trigger);
    
    static void example_callback(char cb);
};

void* example_obj;

example::example()
{
  example_obj = (void*)this;
}

void example::begin()
{
  //Set up everything to do with external library,peripherals,ect...

  //Register the callback with the library
  //register_callback(&example_callback);
}

//Static func that does something
void example::example_callback(char cb)
{
  //Have to do this because the args need to match the library's requirements
  example* self = (example*) example_obj;

  //Do some processing...
  self->do_something(cb);
}

//Add a function pointer and its command char to the vector
void example::add_func(char command,callback_function func)
{
    std::pair<char,callback_function>* new_pair = new std::pair<char,func);
    this->funcs.insert(*new_pair);
}

//This function is called from the callback
void example::do_something(char trigger)
{
  cout << "funcs.size() = "<< (this->funcs.size())<<"\n"; //Always returns the correct size all of the time

  for  (std::map<char,callback_function>::iterator it = this->funcs.begin();
        it != this->funcs.end(); 
        ++it)
  {
    cout << "funcs[i].first = "<< (it->first)<<"\n";
    if (trigger == it->first)
    {
        (it->second)();
    }
  }
}

void callback()
{
    cout << "Callback Called!";
}

int main()
{
    cout << "Starting program...\n";
    
    cout << "Creating example object...\n";
    example ex;
    
    cout << "Adding some callbacks...\n";
    ex.add_func('x',callback);
    ex.add_func('y',callback);
    ex.add_func('z',callback);
    
    cout << "Firing callback...\n";
    example::example_callback('z');
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-