2024年12月28日土曜日

XIAO nRF52840で加速度センサデータを飛ばす(2)

 


加速度センサの計測結果をBLEで飛ばすっていう試み。XIAO nRF52840と秋月AE-ADXL367を使って。
 
ではnRF52840でデータを飛ばしてみる。
基本はXIAO nRF5240のexampleのperipheral bleuartをそのまんま使う。で
ADXL367ctrl1.ino
  1. /*********************************************************************
  2.  This is an example for our nRF52 based Bluefruit LE modules
  3.  
  4.  Pick one up today in the adafruit shop!
  5.  
  6.  Adafruit invests time and resources providing this open source code,
  7.  please support Adafruit and open-source hardware by purchasing
  8.  products from Adafruit!
  9.  
  10.  MIT license, check LICENSE for more information
  11.  All text above, and the splash screen below must be included in
  12.  any redistribution
  13. *********************************************************************/
  14. #include <bluefruit.h>
  15. #include <Adafruit_LittleFS.h>
  16. #include <InternalFileSystem.h>
  17.  
  18. #include "ADXL367API.h" //2024.12.28 Sunday Engineer
  19.  
  20. // BLE Service
  21. BLEDfu bledfu; // OTA DFU service
  22. BLEDis bledis; // device information
  23. BLEUart bleuart; // uart over ble
  24. BLEBas blebas; // battery
  25.  
  26. void setup(){
  27.     Serial.begin(115200);
  28.  
  29. #if CFG_DEBUG
  30.     // Blocking wait for connection when debug mode is enabled via IDE
  31.     while (!Serial)
  32.         yield();
  33. #endif
  34.  
  35.     Serial.println("Bluefruit52 BLEUART Example");
  36.     Serial.println("---------------------------\n");
  37.  
  38.     // Setup the BLE LED to be enabled on CONNECT
  39.     // Note: This is actually the default behavior, but provided
  40.     // here in case you want to control this LED manually via PIN 19
  41.     Bluefruit.autoConnLed(true);
  42.  
  43.     // Config the peripheral connection with maximum bandwidth
  44.     // more SRAM required by SoftDevice
  45.     // Note: All config***() function must be called before begin()
  46.     Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
  47.  
  48.     Bluefruit.begin();
  49.     Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
  50.     // Bluefruit.setName(getMcuUniqueID()); // useful testing with multiple central connections
  51.     Bluefruit.Periph.setConnectCallback(connect_callback);
  52.     Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
  53.  
  54.     // To be consistent OTA DFU should be added first if it exists
  55.     bledfu.begin();
  56.  
  57.     // Configure and Start Device Information Service
  58.     bledis.setManufacturer("Adafruit Industries");
  59.     bledis.setModel("Bluefruit Feather52");
  60.     bledis.begin();
  61.  
  62.     // Configure and Start BLE Uart Service
  63.     bleuart.begin();
  64.  
  65.     // Start BLE Battery Service
  66.     blebas.begin();
  67.     blebas.write(100);
  68.  
  69.     // Set up and start advertising
  70.     startAdv();
  71.  
  72.     ADXL367setup();//2024.12.28 Sunday Engineer
  73.  
  74.     Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
  75.     Serial.println("Once connected, enter character(s) that you wish to send");
  76. }
  77.  
  78. void startAdv(void){
  79.     // Advertising packet
  80.     Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  81.     Bluefruit.Advertising.addTxPower();
  82.  
  83.     // Include bleuart 128-bit uuid
  84.     Bluefruit.Advertising.addService(bleuart);
  85.  
  86.     // Secondary Scan Response packet (optional)
  87.     // Since there is no room for 'Name' in Advertising packet
  88.     Bluefruit.ScanResponse.addName();
  89.  
  90.     /* Start Advertising
  91.      * - Enable auto advertising if disconnected
  92.      * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
  93.      * - Timeout for fast mode is 30 seconds
  94.      * - Start(timeout) with timeout = 0 will advertise forever (until connected)
  95.      *
  96.      * For recommended advertising interval
  97.      * https://developer.apple.com/library/content/qa/qa1931/_index.html
  98.      */
  99.     Bluefruit.Advertising.restartOnDisconnect(true);
  100.     Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
  101.     Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
  102.     Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
  103. }
  104.  
  105. void loop(){
  106.     // Forward data from HW Serial to BLEUART
  107.     while (Serial.available()){
  108.         // Delay to wait for enough input, since we have a limited transmission buffer
  109.         delay(2);
  110.  
  111.         uint8_t buf[64];
  112.         int count = Serial.readBytes(buf, sizeof(buf));
  113.         bleuart.write(buf, count);
  114.     }
  115.  
  116.     // Forward from BLEUART to HW Serial
  117.     while (bleuart.available()){
  118.         uint8_t ch;
  119.         ch = (uint8_t)bleuart.read();
  120.         Serial.write(ch);
  121.     }
  122.     if(ADXL367task()){bleuart.write(ADXL367sendbuf, 15);}//2024.12.28 Sunday Engineer
  123. }
  124. // callback invoked when central connects
  125. void connect_callback(uint16_t conn_handle){
  126.     // Get the reference to current connection
  127.     BLEConnection *connection = Bluefruit.Connection(conn_handle);
  128.  
  129.     char central_name[32] = {0};
  130.     connection->getPeerName(central_name, sizeof(central_name));
  131.  
  132.     Serial.print("Connected to ");
  133.     Serial.println(central_name);
  134. }
  135.  
  136. /**
  137.  * Callback invoked when a connection is dropped
  138.  * @param conn_handle connection where this event happens
  139.  * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
  140.  */
  141. void disconnect_callback(uint16_t conn_handle, uint8_t reason){
  142.     (void)conn_handle;
  143.     (void)reason;
  144.  
  145.     Serial.println();
  146.     Serial.print("Disconnected, reason = 0x");
  147.     Serial.println(reason, HEX);
  148. }
こちらには3箇所追記しただけ、で、
 
ADXL367API.h
  1. #ifndef ADXL367API_H_
  2. extern char ADXL367sendbuf[16];
  3. extern void ADXL367setup(void);
  4. extern uint8_t ADXL367task(void);
  5. #define ADXL367API_H_
  6. #endif
 
ADXL367API.cpp
  1. #include <SPI.h>
  2. #define pinMOSI (10)
  3. #define pinMISO (9)
  4. #define pinSCK (8)
  5. #define pinCS (7)
  6. #define pinDRDY (6)
  7. #define ADDRESS_INTMAP1_LOWER (0x2A)
  8. #define ADDRESS_FILTER_CTL (0x2C)
  9. #define ADDRESS_POWER_CTL (0x2D)
  10. #define ADDRESS_STATUS (0x0B)
  11. #define ADDRESS_XDATA_H (0x0E)
  12. #define ADDRESS_XDATA_L (0x0F)
  13. #define ADDRESS_YDATA_H (0x10)
  14. #define ADDRESS_YDATA_L (0x11)
  15. #define ADDRESS_ZDATA_H (0x12)
  16. #define ADDRESS_ZDATA_L (0x13)
  17. #define ADDRESS_SOFT_RESET (0x1F)
  18. #define VALUE_INTMAP1_LOWER (0x81)
  19. #define VALUE_FILTER_CTL (0x40)
  20. #define VALUE_POWER_CTL (0x02)
  21. #define VALUE_SOFT_RESET (0x52)
  22. SPISettings mySPISettings=SPISettings(1000000,MSBFIRST,SPI_MODE0);
  23. void SPI_writeRegister(uint8_t adr,uint8_t data){
  24.     uint8_t txbuf[3];
  25.     uint8_t rxbuf[3];
  26.     txbuf[0]=0x0A;
  27.     txbuf[1]=adr;
  28.     txbuf[2]=data;
  29.     digitalWrite(pinCS,LOW);
  30.     delayMicroseconds(1);
  31.     SPI.transfer(txbuf,rxbuf,3);
  32.     delayMicroseconds(1000);
  33.     digitalWrite(pinCS,HIGH);
  34. }
  35. uint8_t SPI_readRegister(uint8_t adr){
  36.     uint8_t txbuf[3];
  37.     uint8_t rxbuf[3];
  38.     txbuf[0]=0x0B;
  39.     txbuf[1]=adr;
  40.     txbuf[2]=0x00;
  41.     digitalWrite(pinCS,LOW);
  42.     delayMicroseconds(1);
  43.     SPI.transfer(txbuf,rxbuf,3);
  44.     delayMicroseconds(1000);
  45.     digitalWrite(pinCS,HIGH);
  46.     return rxbuf[2];
  47. }
  48. volatile uint8_t drdy_detected;
  49. void interruptHandler_pinDRDY(){
  50.     drdy_detected=1;
  51. }
  52. void readStatusAndData(uint8_t* buf){
  53.     buf[0]=SPI_readRegister(ADDRESS_STATUS);
  54.     buf[1]=SPI_readRegister(ADDRESS_XDATA_H);
  55.     buf[2]=SPI_readRegister(ADDRESS_XDATA_L);
  56.     buf[3]=SPI_readRegister(ADDRESS_YDATA_H);
  57.     buf[4]=SPI_readRegister(ADDRESS_YDATA_L);
  58.     buf[5]=SPI_readRegister(ADDRESS_ZDATA_H);
  59.     buf[6]=SPI_readRegister(ADDRESS_ZDATA_L);
  60. }
  61. const char char_array[]="0123456789ABCDEF";
  62. void hex2chars(uint8_t src,char* tgt){
  63.   tgt[0]=char_array[(src>>4)&0x0F];
  64.   tgt[1]=char_array[(src>>0)&0x0F];
  65. }
  66. void bytes2chars(uint8_t n,char* strbuf,uint8_t* bytedata){
  67.     uint8_t i;
  68.     for(i=0;i<n;i++){
  69.         hex2chars(bytedata[i],&strbuf[i*2]);
  70.     }
  71.     strbuf[n*2]='\n';
  72. }
  73.  
  74. uint8_t buf[7];
  75. char ADXL367sendbuf[16];
  76.  
  77. void ADXL367setup(){
  78.     uint8_t temp;
  79.     drdy_detected=0;
  80.     pinMode(pinCS,OUTPUT);
  81.     pinMode(pinMOSI,OUTPUT);
  82.     pinMode(pinSCK,OUTPUT);
  83.     pinMode(pinMISO,INPUT);
  84.     digitalWrite(pinCS,HIGH);
  85.     digitalWrite(pinMOSI,LOW);
  86.     digitalWrite(pinSCK,LOW);
  87.     pinMode(pinDRDY,INPUT_PULLUP);
  88.     SPI.begin();
  89.     SPI.beginTransaction(mySPISettings);
  90.     SPI_writeRegister(ADDRESS_SOFT_RESET,VALUE_SOFT_RESET);
  91.     temp=SPI_readRegister(ADDRESS_INTMAP1_LOWER);
  92.     while(temp!=VALUE_INTMAP1_LOWER){
  93.         SPI_writeRegister(ADDRESS_INTMAP1_LOWER,VALUE_INTMAP1_LOWER);
  94.         temp=SPI_readRegister(ADDRESS_INTMAP1_LOWER);
  95.     }
  96.     temp=SPI_readRegister(ADDRESS_FILTER_CTL);
  97.     while(temp!=VALUE_FILTER_CTL){
  98.         SPI_writeRegister(ADDRESS_FILTER_CTL,VALUE_FILTER_CTL);
  99.         temp=SPI_readRegister(ADDRESS_FILTER_CTL);
  100.     }
  101.     temp=SPI_readRegister(ADDRESS_POWER_CTL);
  102.     while(temp!=VALUE_POWER_CTL){
  103.         SPI_writeRegister(ADDRESS_POWER_CTL,VALUE_POWER_CTL);
  104.         temp=SPI_readRegister(ADDRESS_POWER_CTL);
  105.     }
  106.  
  107.     delay(100);
  108.     readStatusAndData(buf);
  109.     attachInterrupt(digitalPinToInterrupt(pinDRDY),interruptHandler_pinDRDY,FALLING);
  110. }
  111.  
  112. uint8_t ADXL367task(){
  113.     uint8_t ret=0;
  114.     if(drdy_detected){
  115.         drdy_detected=0;
  116.         readStatusAndData(buf);
  117.         bytes2chars(7,ADXL367sendbuf,buf);
  118.         ret=1;
  119.     }else{
  120.         ret=0;
  121.     }
  122.     return ret;
  123. }
まぁ、こんな感じで。
で、スマホでSerial Bluetooth Terminalってアプリで、見ることができるわけだが、パソコンで見たいってときは、こちら(https://coskxlabsite.stars.ne.jp/html/for_students/iot/XIAOESP32S3/ESP32S3BLEServer_WinPC.html)がイケてる。ページ下の方のBLE_serial_terminalをダウンロードする。windows ble serial terminalとかで検索すると、BLEをCOMに割り当てる方法とか書いてるんだけど、どうもXIAO nRF5240のexampleのperipheral bleuartはその使い方は想定してないらしくて、すぐ切断されるので、COMへの割り当てすらできない。で、上記アプリでやってみると、
すごくいい。ちゃんとBLEでデータが飛んでるってのが簡単にわかるので助かるー。
 
2024年もあと数日、感謝の気持ちとともに、できるだけ、がんばる。、、、できるだけよ。

0 件のコメント:

コメントを投稿