M5NanoC6、NeoPixel8x8を無線電送して遊ぶ。(ブロードキャスト)(ESP-NOW)(ON-OFF,行,列,RGB1...)




参考

https://qiita.com/caa45040/items/963c222f47b9f43def3a


x 過去ログを見よ!!
x 3.0.7
x ブロードキャストがわかる人
x なぜかUSBシリアルが失敗するのでなんどか「シリアルモニタ」を開きなおす



ex

8x8

OFF,0,7,R0,G0,B0,...R7,G7,B7
OFF,1,7,R0,G0,B0,...R7,G7,B7
OFF,2,7,R0,G0,B0,...R7,G7,B7
OFF,3,7,R0,G0,B0,...R7,G7,B7
OFF,4,7,R0,G0,B0,...R7,G7,B7
OFF,5,7,R0,G0,B0,...R7,G7,B7
OFF,6,7,R0,G0,B0,...R7,G7,B7
ON,7,7,R0,G0,B0,...R7,G7,B7

1個だけ送る

ON,0,0,R0,G0,B0,...x,x,x


データ構造

//行、列、RGB
char Pixel[8][8][3];


イメージ

![o_coq641.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/60699c9a-7b58-83f2-dbe2-7b8c956b04da.jpeg)

イメージ

![o_coq643.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c440f4bf-529d-c422-84a9-f7d1713645de.jpeg)

イメージ

![o_coq646.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/0485be4b-9727-3624-dfdf-8232d9347e27.jpeg)


結果

![o_coq644.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e5e359c4-8c8f-0715-4531-e5b3902688c2.jpeg)


![o_coq645.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f5411004-bef4-7485-17d4-d3e0fec61ce6.jpeg)


プログラム

スレーブ　NanoC6 WS2812側


```c++



//ESP32_NOW_s_NeoPixel8x8_M5NanoC6_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"

#include <Adafruit_NeoPixel.h>


//定義
#define NUM_LEDS 64
Adafruit_NeoPixel strip(NUM_LEDS, 2, NEO_GRB + NEO_KHZ800);


static volatile unsigned char Pixel[8][8][3];
static volatile int OnOff;
static volatile int line;
static volatile int column;


/* Definitions */

#define ESPNOW_WIFI_CHANNEL 1

/* 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) {

    //Serial.printf("\r\nlen=[%d]\r\n",len);

    OnOff = 0;

    if(len > 5){

      OnOff   = data[0];
      line    = data[1];
      column  = data[2];

      //Serial.printf("OnOff  = %d\n",OnOff);
      //Serial.printf("line   = %d\n",line);
      //Serial.printf("column = %d\n",column);

        
      int pt;
      for(int i=0;i<(column+1);i++){
        
        pt = 3 * i + 3;
        Pixel[line][i][0] = data[pt++];
        Pixel[line][i][1] = data[pt++];
        Pixel[line][i][2] = data[pt  ];
    
      }

    }//enfif len

    if(OnOff != 0) {Serial.printf("\r\nOnOff\r\n");};
    
    Serial.printf("Received a message from master " MACSTR " (%s)\n", MAC2STR(addr()), broadcast ? "broadcast" : "unicast");
    Serial.printf("  Message: %s\n", (char *)"...");
  }
};

/* 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");
  }
}


/* Main */

void setup() {

  //RGB LED
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);

  strip.begin();
  strip.show();

  //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(); //リセット
  }

  //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...");
}

void loop() {

    //on-off
    //if( 0 != 0 ){
    if(OnOff != 0) {

      //Serial.printf("OnOff  = %d\n",OnOff);
      //Serial.printf("line   = %d\n",line);
      //Serial.printf("column = %d\n",column);

      int k = 0;
      for(int i=0;i<(line+1);i++){
        for(int j=0;j<(column+1);j++){

            strip.setPixelColor(k,strip.Color(
                Pixel[i][j][0],Pixel[i][j][1],Pixel[i][j][2]));
            
            //strip.show();
            //Serial.printf(".");
            
            k++;
        }//for j
        //Serial.printf("\n");
      }//for i
      //Serial.printf("\n");
    }//on-off

    //strip.setPixelColor(0,strip.Color(64,64,64));
    //strip.setPixelColor(1,strip.Color(64,64,64));
    //strip.show();
    //delay(300);//ダミー

    //strip.setPixelColor(0,strip.Color(64,0,0));
    //strip.setPixelColor(1,strip.Color(64,0,0));
    strip.show();


    delay(300);//ダミー
   
}//loop



```

ホスト stampS3

```c++




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


//インクルド
#include "ESP32_NOW.h"
#include "WiFi.h"
#include <esp_mac.h>  // For the MAC2STR and MACSTR macros

//#include "MacAddress.h"


//定義
/* 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
  char pp[]={0,0,0,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7};
  delay(5);
  broadcast_peer.send_message(CP(pp), 27+1);
  delay(5);
  broadcast_peer.send_message(CP(pp), 27+1);
  delay(5);
  broadcast_peer.send_message(CP(pp), 27+1);
  delay(5);

}//setup


//            0 1 2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6
char hh0[] = {0,0,7, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64};
char hh1[] = {0,1,7, 64,64,64,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,64,64,64};
char hh2[] = {0,2,7, 64,64,64,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,64,64,64};
char hh3[] = {0,3,7, 64,64,64,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,64,64,64};
char hh4[] = {0,4,7, 64,64,64,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,64,64,64};
char hh5[] = {0,5,7, 64,64,64,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,64,64,64};
char hh6[] = {0,6,7, 64,64,64,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,64,64,64};
char hh7[] = {4,7,7, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64};

char hh8[] = {0,0,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};
char hh9[] = {0,1,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};
char h10[] = {0,2,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};
char h11[] = {0,3,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};
char h12[] = {0,4,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};
char h13[] = {0,5,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};
char h14[] = {0,6,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};
char h15[] = {3,7,7, 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11};

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

  //                       123456789012345678901234567
  broadcast_peer.send_message(CP(hh0), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh1), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh2), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh3), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh4), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh5), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh6), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh7), 27+1);delay(5);
  delay(1000);

  //                       123456789012345678901234567
  broadcast_peer.send_message(CP(hh8), 27+1);delay(5);
  broadcast_peer.send_message(CP(hh9), 27+1);delay(5);
  broadcast_peer.send_message(CP(h10), 27+1);delay(5);
  broadcast_peer.send_message(CP(h11), 27+1);delay(5);
  broadcast_peer.send_message(CP(h12), 27+1);delay(5);
  broadcast_peer.send_message(CP(h13), 27+1);delay(5);
  broadcast_peer.send_message(CP(h14), 27+1);delay(5);
  broadcast_peer.send_message(CP(h15), 27+1);delay(5);
  delay(1000);

}//loop


```


-------------------------

おまけ　デバッグ
-------------------------

オンラインコンパイラ

電文データを仮想VRAMにストックする

ON-OFF,行,列,データ1...

char Pixel[8][8][3];

```c++


#include <iostream>
using namespace std;


int main(void){
    // Your code here!
    //           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
    char hh[] = {4,5,7,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8};
    
    const uint8_t *data;
    int len;
    
    data = (uint8_t *)hh;
    len = 27;
    
    char Pixel[8][8][3];
    int on_off;
    int line;
    int column;
    
    
    on_off  = data[0];
    line    = data[1];
    column  = data[2];
    
    printf("on_off = %d\n",on_off);
    printf("line   = %d\n",line);
    printf("column = %d\n",column);
    
    
    int pt;
    for(int i=0;i<(column+1);i++){
        
        pt = 3 * i + 3;
        Pixel[line][i][0] = data[pt++];
        Pixel[line][i][1] = data[pt++];
        Pixel[line][i][2] = data[pt  ];
    
    }
    
    for(int i=0;i<8;i++){
        printf("%d,",Pixel[5][i][0]);
        printf("%d,",Pixel[5][i][1]);
        printf("%d:",Pixel[5][i][2]);
    }

}



```


```

on_off = 4
line   = 5
column = 7
1,1,1:2,2,2:3,3,3:4,4,4:5,5,5:6,6,6:7,7,7:8,8,8:


```

仮想VRAMの内容をRGB LEDに転送する

```c++

#include <iostream>
using namespace std;


void Q_setPixelColor(int x){printf("[%3d]",x);}
void Q_Color(char r, char g, char b){printf("(%d%d%d)",r,g,b);}


int main(void){
    // Your code here!
    
    char Pixel[8][8][3] = {
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} },  
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} },  
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} },  
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} },  
        
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} },  
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} },  
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} },  
      { {1,1,1},{2,2,2},{3,3,3},{4,4,4},{5,5,5},{6,6,6},{7,7,7},{8,8,8} }  
    };

    int on_off;
    int line;
    int column;
    
    
    on_off  = 0xff;
    line    = 7;
    column  = 7;
    
    printf("on_off = %d\n",on_off);
    printf("line   = %d\n",line);
    printf("column = %d\n",column);
    
    
    //line = 5
    //for(int i=0;i<8;i++){
    //    printf("%d,",Pixel[5][i][0]);
    //    printf("%d,",Pixel[5][i][1]);
    //    printf("%d:",Pixel[5][i][2]);
    //}
    //printf("\n");
    
    //on-off
    if(on_off != 0){
    
    int k = 0;
    for(int i=0;i<(line+1);i++){
        for(int j=0;j<(column+1);j++){
            //printf("%c",'0'+j);
            
            Q_setPixelColor(k);Q_Color(
                Pixel[i][j][0],Pixel[i][j][1],Pixel[i][j][2]);
            
            k++;
        }//for j
        printf("\n");
    }//for i
    
    }//on-off
    
}//main



```



```


on_off = 255
line   = 7
column = 7
[  0](111)[  1](222)[  2](333)[  3](444)[  4](555)[  5](666)[  6](777)[  7](888)
[  8](111)[  9](222)[ 10](333)[ 11](444)[ 12](555)[ 13](666)[ 14](777)[ 15](888)
[ 16](111)[ 17](222)[ 18](333)[ 19](444)[ 20](555)[ 21](666)[ 22](777)[ 23](888)
[ 24](111)[ 25](222)[ 26](333)[ 27](444)[ 28](555)[ 29](666)[ 30](777)[ 31](888)
[ 32](111)[ 33](222)[ 34](333)[ 35](444)[ 36](555)[ 37](666)[ 38](777)[ 39](888)
[ 40](111)[ 41](222)[ 42](333)[ 43](444)[ 44](555)[ 45](666)[ 46](777)[ 47](888)
[ 48](111)[ 49](222)[ 50](333)[ 51](444)[ 52](555)[ 53](666)[ 54](777)[ 55](888)
[ 56](111)[ 57](222)[ 58](333)[ 59](444)[ 60](555)[ 61](666)[ 62](777)[ 63](888)


```