続)速度倍増)M5NanoC6、加速度センサー(ADXL345)を無線電送して遊ぶ。(ESP-NOW)(リングバッファ)





x 過去ログを見よ!!
x 3.0.7
x ブロードキャストがわかる人
x 主な処理をPCで行う為にマイコン側では、最小限の変換処理しか行いません。
x 2の補数のほぼすべての技術が必要です。
x なぜかUSBシリアルが失敗するのでシリアルモニタを開いたり閉じたりしてください
x Zに関しては、高校の教科書の大砲ネタでは、-9.8で落下
x Zに関しては、加速度センサーを主にした時は、+9.8
x Zは、加速度センサーからは、約10程度の適当な値が出るが気にするな!!


目的
加速度センサーの値を無線を通して、PCに電送して遊ぶ。
加速度センサー側は、最小限とする。
なるべく多くの加速度センサーの値を送る
リングバッファは、符号なし8ビット6バイトとする。
無線区間は、16ビット符号ありの整数、3値、6バイトとする。
ビットの並びと、バイトの並びは、上位から下位とする
バイトの並び
上位バイト、下位バイト
ビットの並び
b16,b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
型

見やすさ、わかりやすさ重視の為に教科書的な変換を採用

```

●符号を外す
if( 0<a ) {a = 0 - a;} 

●符号を付ける
a = 0 - a;

●符号を取ったaを128から255の間に配置する
a = 256 - a;

●128から255に符号を調べる
if( a > 127 ) {}

●128から255の間を符号あり整数にする
a = a - 256;

●符号が付いたままの整数を128から255にする
a = 256 + a;

```


なぜか、zの符号が基板に対して反転したままだが特に直さない(あっている?)

イメージ

```c++


#define aaa_x -0.01f
#define aaa_y -0.02f
#define aaa_z -0.03f

int ai_x,ai_y,ai_z;
int al; //一時
unsigned char ac[6];


//符号を外して付ける処理がない

ai_x = (int)(aaa_x * 1000.0f);
printf("%d\n",ai_x);
if(ai_x < 0) {
  ai_x = (ai_x - 5) / 10;
  if( ai_x < -9999){ ai_x = -9999;}
  ai_x = 65536 + ai_x;  
} else {
  ai_x = (ai_x + 5) / 10;
  if( ai_x > 9999){ ai_x = 9999;}
}
printf("%d\n",ai_x);

ai_y = (int)(aaa_y * 1000.0f);
printf("%d\n",ai_y);
if(ai_y < 0) {
  ai_y = (ai_y - 5) / 10;
  if( ai_y < -9999){ ai_y = -9999;}
  ai_y = 65536 + ai_y; 
} else {
  ai_y = (ai_y + 5) / 10; 
  if( ai_y > 9999){ ai_y = 9999;}
}
printf("%d\n",ai_y);

ai_z = (int)(aaa_z * 1000.0f);
printf("%d\n",ai_z);
if(ai_z < 0) {
  ai_z = (ai_z - 5) / 10;
  if( ai_z < -9999){ ai_z = -9999;}
  ai_z = 65536 + ai_z;
} else {
  ai_z = (ai_z + 5) / 10;
  if( ai_z > 9999){ ai_z = 9999;}
}
printf("%d\n",ai_z);


//符号を外す処理


//x
ac[0] = ai_x >> 8;
ac[1] = ai_x & 0xff;
printf("x %d\n", 256*ac[0]+ac[1]);

//y
ac[2] = ai_y >> 8;
ac[3] = ai_y & 0xff;
printf("y %d\n", 256*ac[2]+ac[3]);

//z
ac[4] = ai_z >>8;
ac[5] = ai_z & 0xff;
printf("z %d\n", 256*ac[4]+ac[5]);



```


値は、10進固定小数点2桁とする。
受信側は、整数を受け型を変換する
-00.00,-00.00,-09.80

イメージ

```c++

unsigned char ac[6];
int al;
char str1[] = "-00.00,-00.00,-09.80";


//符号を付ける処理

str1[20] = 0;

al = 1234;
ac[4] = al >> 8;
ac[5] = al & 0xff;

//z
al = 256 * ac[4] + ac[5];
printf("%d\n",al);
str1[14] = ' ';
if ( al > 32767) {str1[14] = '-' ;  al = 65536 - al; }/*符号*/
printf("%d\n",al);

str1[19] = '0' + al % 10;
al = al / 10;
str1[18] = '0' + al % 10;

str1[17] = '.';

al = al / 10;
str1[16] = '0' + al % 10;
str1[15] = '0' + al / 10;

printf("%s\n",str1);

//str1[14] = '-'; //符号

str1[13] = ',';


al = 1234;
ac[2] = al >> 8;
ac[3] = al & 0xff;


//y
al = 256 * ac[2] + ac[3];
printf("%d\n",al);
str1[7] = ' ';
if ( al > 32767) {str1[7] = '-' ;  al = 65536 - al; } //符号
printf("%d\n",al);

str1[12] = '0' + al % 10;
al = al / 10;
str1[11] = '0' + al % 10;

str1[10] = '.';

al = al / 10;
str1[9] = '0' + al % 10;
str1[8] = '0' + al / 10;

printf("%s\n",str1);



//str1[7] = '0' + al //符号

str1[6] = ',';

al = 65536-1;
ac[0] = al >> 8;
ac[1] = al & 0xff;

//x
al = 256 * ac[0] + ac[1];
printf("%d\n",al);
str1[0] = ' ';
if ( al > 32767) {str1[0] = '-' ;  al = 65536 - al; }  //符号
printf("%d\n",al);


str1[5] = '0' + al % 10;
al = al / 10;
str1[4] = '0' + al % 10;
al = al / 10;

str1[3] = '.';

str1[2] = '0' + al % 10;
str1[1] = '0' + al / 10;

//str1[0] = '0' + al //符号

printf("%s\n",str1);


```


●結果

![o_coq652.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4ec09768-933c-a9a6-94ec-ef25f57cd3db.jpeg)

![o_coq653.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3bfe5f8e-6ea1-1c64-a55a-97c68ab37926.jpeg)





![o_coq649.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f690f5f3-c686-0249-0b23-4d4c30c71d2a.jpeg)


![o_coq650.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/80fc3963-0df2-8127-a7a5-eca7663570be.jpeg)


プログラム


送信　NanoC6 加速度センサー


```c++



//ESP32_NOW_m_ADXL345_ring_M5NanoC6_1
//1対1に改造する　対応
//ブロードキャスト


//インクルド
//加速度センサー
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
//ESP-NOW
#include "ESP32_NOW.h"
#include "WiFi.h"
#include <esp_mac.h>  // For the MAC2STR and MACSTR macros


//定義
//加速度センサー
/* Assign a unique ID to this sensor at the same time */

Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

/* Definitions */
//WiFiチャンネルの指定
#define ESPNOW_WIFI_CHANNEL 1

//クラス
/* Classes */

// Creating a new class that inherits from the ESP_NOW_Peer class is required.

class ESP_NOW_Broadcast_Peer : public ESP_NOW_Peer {
  public:
    // Constructor of the class using the broadcast address
    ESP_NOW_Broadcast_Peer(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) : ESP_NOW_Peer(mac_addr, channel, iface, lmk) {}

    // Destructor of the class
    ~ESP_NOW_Broadcast_Peer() {
      remove();
    }

    // Function to properly initialize the ESP-NOW and register the broadcast peer
    bool begin() {
      if (!ESP_NOW.begin() || !add()) {
        log_e("Failed to initialize ESP-NOW or register the broadcast peer");
        return false;
      }
      return true;
    }

    // Function to send a message to all devices within the network
    bool send_message(const uint8_t *data, size_t len) {
      if (!send(data, len)) {
        log_e("Failed to broadcast message");
        return false;
      }
      return true;
    }
};

/* Global Variables */

//ブロードキャスト オブジェクトの定義
// Create a broadcast peer object
ESP_NOW_Broadcast_Peer broadcast_peer(ESP_NOW.BROADCAST_ADDR, ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);

//const MacAddress peer_mac({0x48, 0x27, 0xe2, 0xe3, 0xbd, 0x50});
//ESP_NOW_Broadcast_Peer broadcast_peer(  peer_mac  , ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);


/* Main */

#define CP (uint8_t *)

//初期化
void setup() {

  //WiFiの初期化
  // Initialize the Wi-Fi module
  WiFi.mode(WIFI_STA);
  WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
  delay(3000);//決め打ちなので、おかしかったら調整してね!

  //ブロードキャストの初期化
  // Register the broadcast peer
  if (!broadcast_peer.begin()) {
    delay(5000); //瞬リセット防止用
    ESP.restart(); //リセット
  }//endif

  //テストメッセージを送る debug
  //         012345
  char pp[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  delay(5);
  broadcast_peer.send_message(CP(pp), 6 + 0);
  delay(5);
  broadcast_peer.send_message(CP(pp), 6 + 0);
  delay(5);
  broadcast_peer.send_message(CP(pp), 6 + 0);
  delay(5);

  /* Initialise the sensor */
  if (!accel.begin()) { //失敗
    /* There was a problem detecting the ADXL345 ... check your connections */

    while (1) {
      delay(1);
    };//無限ループ
  }//endif

  /* Set the range to whatever is appropriate for your project */
  accel.setRange(ADXL345_RANGE_16_G);

}//setup


//            012345
unsigned char ac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

//メインループ
void loop() {

  int ai_x, ai_y, ai_z;

  /* Get a new sensor event */
  sensors_event_t event;
  accel.getEvent(&event);

  //x
  ai_x = (int)(((float)(event.acceleration.x)) * 1000.0f);
  if (ai_x < 0) { //符号を外して付ける処理の類似
    ai_x = (ai_x - 5) / 10;
    if( ai_x < -9999){ ai_x = -9999;}
    ai_x = 65536 + ai_x;  //符号を外す処理
  } else {
    ai_x = (ai_x + 5) / 10;
    if( ai_x > 9999){ ai_x = 9999;}
  }

  //y
  ai_y = (int)(((float)(event.acceleration.y)) * 1000.0f);
  if (ai_y < 0) {
    ai_y = (ai_y - 5) / 10;
    if( ai_y < -9999){ ai_y = -9999;}
    ai_y = 65536 + ai_y;
  } else {
    ai_y = (ai_y + 5) / 10;
    if( ai_y > 9999){ ai_y = 9999;}
  }

  //z
  ai_z = (int)(((float)(event.acceleration.z)) * 1000.0f);
  if (ai_z < 0) {
    ai_z = (ai_z - 5) / 10;
    if( ai_z < -9999){ ai_z = -9999;}
    ai_z = 65536 + ai_z;
  } else {
    ai_z = (ai_z + 5) / 10;
    if( ai_z > 9999){ ai_z = 9999;}
  }


  //上位バイトと下位バイトに分割する処理

  //x
  ac[0] = ai_x >> 8;
  ac[1] = ai_x & 0xff;

  //y
  ac[2] = ai_y >> 8;
  ac[3] = ai_y & 0xff;

  //z
  ac[4] = ai_z >> 8;
  ac[5] = ai_z & 0xff;

  broadcast_peer.send_message(CP(ac), 6 + 0); delay(5);
  delay(300);

}//loop



```

受信　StampS3 USBシリアル出力

```c++



//ESP32_NOW_s_ADXL345_ring_M5StampS3_1
//1対1に改造する　対応
//ブロードキャスト


/*
    ESP-NOW Broadcast Slave
    Lucas Saavedra Vaz - 2024

    This sketch demonstrates how to receive broadcast messages from a master device using the ESP-NOW protocol.

    The master device will broadcast a message every 5 seconds to all devices within the network.

    The slave devices will receive the broadcasted messages. If they are not from a known master, they will be registered as a new master
    using a callback function.
*/


//インクルド
#include <Arduino.h>

#include "ESP32_NOW.h"
#include "WiFi.h"

#include <esp_mac.h>  // For the MAC2STR and MACSTR macros

#include <vector>

#include "MacAddress.h"


//定義
/* Definitions */

#define ESPNOW_WIFI_CHANNEL 1

//プロトタイプ宣言
int acceleration_num();
void acceleration_write(unsigned char *a);
void acceleration_read(unsigned char *a);


//クラス
/* Classes */

// Creating a new class that inherits from the ESP_NOW_Peer class is required.

class ESP_NOW_Peer_Class : public ESP_NOW_Peer {
  public:
    // Constructor of the class
    ESP_NOW_Peer_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) : ESP_NOW_Peer(mac_addr, channel, iface, lmk) {}

    // Destructor of the class
    ~ESP_NOW_Peer_Class() {}

    // Function to register the master peer
    bool add_peer() {
      if (!add()) {
        log_e("Failed to register the broadcast peer");
        return false;
      }
      return true;
    }

    // Function to print the received messages from the master
    void onReceive(const uint8_t *data, size_t len, bool broadcast) {

      //キューイング、リングバッファへの書き込み
      acceleration_write((unsigned char *)data);

      //Serial.printf("Received a message from master " MACSTR " (%s)\n", MAC2STR(addr()), broadcast ? "broadcast" : "unicast");
      //Serial.printf("  Message: %s\n", (char *)data);
    }
};

/* Global Variables */

// List of all the masters. It will be populated when a new master is registered
std::vector<ESP_NOW_Peer_Class> masters;

/* Callbacks */

// Callback called when an unknown peer sends a message
void register_new_master(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg) {

  //自分
  const MacAddress peer_mac1( {0x48, 0x27, 0xe2, 0xe3, 0xbd, 0x50});
  unsigned char a_add[6] = {0x48, 0x27, 0xe2, 0xe3, 0xbd, 0x50};
  //相手
  const MacAddress peer_mac2( {0x40, 0x4c, 0xca, 0x5a, 0xe3, 0x1c});

  if (memcmp(info->des_addr, ESP_NOW.BROADCAST_ADDR, 6) == 0) {
    //if (memcmp(info->des_addr, a_add, 6) == 0) {
    Serial.printf("Unknown peer " MACSTR " sent a broadcast message\n", MAC2STR(info->src_addr));
    Serial.println("Registering the peer as a master");



    ESP_NOW_Peer_Class new_master(info->src_addr, ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);

    masters.push_back(new_master);
    if (!masters.back().add_peer()) {
      Serial.println("Failed to register the new master");
      return;
    }
  } else {
    // The slave will only receive broadcast messages
    log_v("Received a unicast message from " MACSTR, MAC2STR(info->src_addr));
    log_v("Igorning the message");
  }
}


//lllllllllllllllllllllllllllllllllllllllll
//キューイング、リングバッファ

unsigned char acceleration_stack[256][6];

int acceleration_write_point = 0;

int acceleration_read_point = 0;

//リングバッファ内の書き込み個数を返す
int acceleration_num() {

  int a = acceleration_write_point - acceleration_read_point;
  if (a < 0) {
    a = 256 + acceleration_write_point - acceleration_read_point;
  }

  return (a);
}


//キューイング、リングバッファへの書き込み
void acceleration_write(unsigned char *a) {

  //printf("write_point=[%d]\n",acceleration_write_point);

  //printf(">%d\n",a[0]);
  acceleration_stack[acceleration_write_point][0] = a[0];
  acceleration_stack[acceleration_write_point][1] = a[1];
  acceleration_stack[acceleration_write_point][2] = a[2];
  acceleration_stack[acceleration_write_point][3] = a[3];
  acceleration_stack[acceleration_write_point][4] = a[4];
  acceleration_stack[acceleration_write_point][5] = a[5];


  //ライトポイントを1個進める
  acceleration_write_point++;
  acceleration_write_point = acceleration_write_point & 0xff;

  if (acceleration_num() > (255 - 1) ) {
    //printf("-");
    //printf("acceleration_num=[%d]\n",acceleration_num());
    //リードポイントを1個進める
    acceleration_read_point++;
    acceleration_read_point = acceleration_read_point & 0xff;
  }
}


//キューイング、リングバッファからの読み込み
void acceleration_read(unsigned char *a) {

  //printf("read_point=[%d]\n",acceleration_read_point);

  a[0] = acceleration_stack[acceleration_read_point][0];
  a[1] = acceleration_stack[acceleration_read_point][1];
  a[2] = acceleration_stack[acceleration_read_point][2];
  a[3] = acceleration_stack[acceleration_read_point][3];
  a[4] = acceleration_stack[acceleration_read_point][4];
  a[5] = acceleration_stack[acceleration_read_point][5];


  if (acceleration_num() != 0 ) {
    //printf(">");
    //printf("acceleration_num=[%d]\n",acceleration_num());
    //リードポイントを1個進める
    acceleration_read_point++;
    acceleration_read_point = acceleration_read_point & 0xff;
  }


}


//lllllllllllllllllllllllllllllllllllllll

/* Main */

//初期化
void setup() {

  //WiFiの初期化
  // Initialize the Wi-Fi module
  WiFi.mode(WIFI_STA);
  WiFi.setChannel(ESPNOW_WIFI_CHANNEL);

  Serial.begin(115200); //シリアルポート
  for (int i = 0; i < 9; i++) {
    Serial.print(".");
    delay(500);//接続待ち
  }//for
  Serial.println();

  while (!WiFi.STA.started()) {
    delay(500);//接続待ち
  }

  //アドレスとWiFiチャンネルの表示
  Serial.println("ESP-NOW Example - Broadcast Slave");
  Serial.println("Wi-Fi parameters:");
  Serial.println("  Mode: STA");
  Serial.println("  MAC Address: " + WiFi.macAddress());
  Serial.printf("  Channel: %d\n", ESPNOW_WIFI_CHANNEL);

  //ブロードキャストの初期化
  // Initialize the ESP-NOW protocol
  if (!ESP_NOW.begin()) {
    Serial.println("Failed to initialize ESP-NOW");
    Serial.println("Reeboting in 5 seconds...");
    delay(5000); //瞬リセット防止用
    ESP.restart(); //リセット
  }//endif

  //ESP-NOWのコールバック
  // Register the new peer callback
  ESP_NOW.onNewPeer(register_new_master, NULL);

  Serial.println("Setup complete. Waiting for a master to broadcast a message...");

}//setup


//メインループ
void loop() {

  unsigned char ac[6];//受信パケット
  int al;//一時
  //             01234567890123456789
  char str1[] = "-00.00,-00.00,-09.80";//出力

  //読み込み、USBシリアル出力処理
  if ( acceleration_num() != 0 ) {//書き込みデータがある場合
  //if ( 0 == 0 ) {//debug

    //キューイング、リングバッファからの読み込み
    acceleration_read((unsigned char *)ac);

    //debug
    //ac[0] = 0x00;
    //ac[1] = 0x01;
    //ac[2] = 0x00;
    //ac[3] = 0x02;
    //ac[4] = 0x00;
    //ac[5] = 0x03;

    //debug
    //al = 65536-1;
    //ac[0] = al >> 8;
    //ac[1] = al & 0xff;

    //debug
    //al = 1234;
    //ac[2] = al >> 8;
    //ac[3] = al & 0xff;

    //debug
    //al = 1234;
    //ac[4] = al >> 8;
    //ac[5] = al & 0xff;

    str1[20] = 0; //終端

    //z
    al = 256 * ac[4] + ac[5];str1[14] = '0';
    if ( al > 32767) {str1[14] = '-' ;  al = 65536 - al; }//符号を付ける処理

    str1[19] = '0' + al % 10;
    al = al / 10;
    str1[18] = '0' + al % 10;

    str1[17] = '.';

    al = al / 10;
    str1[16] = '0' + al % 10;
    str1[15] = '0' + al / 10;

    //str1[14] = '-'; //符号

    str1[13] = ',';//区切り

    //y
    al = 256 * ac[2] + ac[3];str1[7] = '0';
    if ( al > 32767) {str1[7] = '-' ;  al = 65536 - al; } //符号

    str1[12] = '0' + al % 10;
    al = al / 10;
    str1[11] = '0' + al % 10;

    str1[10] = '.';

    al = al / 10;
    str1[9] = '0' + al % 10;
    str1[8] = '0' + al / 10;

    //str1[7] = '0' + al //符号

    str1[6] = ',';//区切り

    //x
    al = 256 * ac[0] + ac[1];str1[0] = '0';
    if ( al > 32767) {str1[0] = '-' ;  al = 65536 - al; }  //符号

    str1[5] = '0' + al % 10;
    al = al / 10;
    str1[4] = '0' + al % 10;
    al = al / 10;

    str1[3] = '.';

    str1[2] = '0' + al % 10;
    str1[1] = '0' + al / 10;

    //str1[0] = '0' + al //符号

    //Serial.printf("Received a message from master " MACSTR " (%s)\n", MAC2STR(addr()), broadcast ? "broadcast" : "unicast");
    //Serial.printf("  Message: %s\n", (char *)data);

    Serial.print((char *)str1);
    Serial.println();

  }//endif

  delay(300);//ダミー

}//loop



```