Simple circuit - Xiao, LED & Vibration

Hello,
Before I dive fully down the rabbit hole that is Seeed Studio, I wanted to ask if my idea would be possible with any of these devices.

Simply put, I want to use one of these devices to connect a vibrating monitor, a LED, and have both activate at command of a bluetooth signal sent from a switch. Would this be possible?

Thank you
Matt

Hi there,
Yes the Nrf52840 Sense version has the IMU onboard. So things like motion, movement , orientation and fall is all available to you. Use the motion detection demo I have on here and it basically detects movement (micro movement/Vibration) if you set the IMU settings correctly and use the interrupts to signal and pass that info to the BLE client.
Give that an Eyeball and ask any questions you might have, Totally doable and great result are achievable. The Xiao “Nrf52840 BLE Sense” is made for it.
You can use the non-Sense version Xiao “Nrf52840 BLE” for the other end Peripheral indicator and readout.(check the demos)
HTH
GL :slight_smile: PJ :v:

1 Like

My uncle used to use vibration analysis to predict bearing failure and maintinance of large industrial machines many years ago… he has passed … he would be ammazed that all this can be done on a XIAO

Hi there,
Try this demo and see if it helps gain some understanding of what you can do , Which is a lot the mcu and onboard IMU are the best thing since Cake and Icecream. ask any questions and more smart folks will reply.
HTH
GL :slight_smile: PJ
:v:

Hi all,

Thank you for these pointers, I’ll give it a try, but I think I might have misled you to the extent of what I want to accomplish.

All I want to do is have a red LED and a vibration motor trigger by command of a received signal.

It’s for a simple movie prop and the unit can’t be as big as the one in the demo.

This page showed a likely circuit Getting Started with Seeed Studio XIAO ESP32C3 | Seeed Studio Wiki where a green LED is shown to be connected up. I realise this might only be for the “Blink” LED process, but I hope it wasn’t.

Kind regards
Matt

Hi there,
Sure, You can use the tiny Grove expansion board and brake off the extra ports you don’t need to keep it small. It works with all of the XIao MCU’s
HTH
GL :slight_smile: PJ
:v:

check out the BLE , LED switch examples. You can use the Nrf blinky app for the phone with those too.
pretty easy and very straight forward.
:+1:


Free Fall Demo…

check out ATtiny see this thread

Hi there,

So I went and did the other LOL here is the code both in Battery and Debug on the expansion board.
It uses the onboard IMU of the Chip.
Red LED is VIM (Vibration,Impact,Motion) can support any of it, easy to add some BLE and send signals either way.
here’s the Video short

and here’s the code.

// debug code added /8/14/24
//
// V I M code Demo
//
// 

#include <LSM6DS3.h>
#include <Wire.h>
#include <U8x8lib.h>

#define DEBUG_MODE // Comment this line out to disable debug mode

LSM6DS3 myIMU(I2C_MODE, 0x6A); // Create an instance of class LSM6DS3
#ifdef DEBUG_MODE
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ PIN_WIRE_SCL, /* data=*/ PIN_WIRE_SDA, /* reset=*/ U8X8_PIN_NONE);
#endif
float aX, aY, aZ, gX, gY, gZ;
const float accelerationThreshold = 1.25; // threshold of significant in G's
const int numSamples = 59;
int samplesRead = numSamples;
const int buttonPin = 1;     // the number of the pushbutton pin
int buttonState = 0;         // variable for reading the pushbutton status
int BuzzerPin = A3;           // A3 , P0.29 PIN 4
uint8_t interruptCount = 0; // Amount of received interrupts
uint8_t prevInterruptCount = 0; // Interrupt Counter from last loop
int buzzer = BuzzerPin;
int Onthemove = 0; // Not Moving Status

void setup() {
  // put your setup code here, to run once:
#ifdef DEBUG_MODE
  Serial.begin(9600);
  delay(1000); // relax...
  Serial.println("Processor came out of reset.\n");
  
  u8x8.begin();
  u8x8.setFlipMode(1);   // set number from 1 to 3, the screen word will rotate 180
  
  pinMode(LED_BUILTIN, OUTPUT); // initialize the LED pin as an output:
  pinMode(buttonPin, INPUT_PULLUP); // initialize the pushbutton pin as an input:
  pinMode(BuzzerPin, OUTPUT);
  pinMode(LEDR, OUTPUT);
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);
  setLedRGB(false, false, true); // set blue led
#endif

  // Call .begin() to configure the IMU
  if (myIMU.begin() != 0) {
#ifdef DEBUG_MODE
    Serial.println("Device error");
#endif
  } else {
#ifdef DEBUG_MODE
    Serial.println("IMU Good");
    Serial.println("aX,aY,aZ,gX,gY,gZ");
#endif
  }

#ifdef DEBUG_MODE
  u8x8.setFont(u8x8_font_8x13B_1x2_r);
  u8x8.clearDisplay();
  u8x8.setCursor(4, 0);
  u8x8.print("Grab Me ");
  u8x8.setCursor(5, 3);
  u8x8.print("&");
  u8x8.setCursor(1, 6);
  u8x8.print("Activity-");
  u8x8.print("Demo");
#endif
}

void loop() {
  // wait for significant motion
  while (samplesRead == numSamples) {
    // read the acceleration data
    aX = myIMU.readFloatAccelX();
    aY = myIMU.readFloatAccelY();
    aZ = myIMU.readFloatAccelZ();

    // sum up the absolutes
    float aSum = fabs(aX) + fabs(aY) + fabs(aZ);

    // check if it's above the threshold
    if (aSum >= accelerationThreshold) {
      // reset the sample read count
      samplesRead = 0;
      setLedRGB(true,false, false); // set RED only
      Onthemove = 1;
#ifdef DEBUG_MODE
      tone (buzzer, 800);
      delay (800);
      noTone(buzzer);
      delay (200);
      u8x8.clearDisplay();
      u8x8.setCursor(5, 3);
      u8x8.print("ON The Move");
#endif
      break;
    }
    setLedRGB(false, true, false); // set green only
#ifndef DEBUG_MODE
    noTone(buzzer);
#endif
  }

  // check if all the required samples have been read since
  // the last time significant motion was detected
  while (samplesRead < numSamples) {
    // read the acceleration and gyroscope data
    samplesRead++;
#ifdef DEBUG_MODE
    // print the data in CSV format
    Serial.print(myIMU.readFloatAccelX(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatAccelY(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatAccelZ(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroX(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroY(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroZ(), 3);
    Serial.println();
#endif
    if (samplesRead == numSamples) {
#ifdef DEBUG_MODE
      // add an empty line if it's the last sample
      Serial.println();
      if (Onthemove != 0 ){
        u8x8.clearDisplay();
        u8x8.setCursor(4, 0);
        u8x8.print("Grab Me ");
        u8x8.setCursor(5, 3);
        u8x8.print("AGAIN");
      }
#endif
    }
  }
}

// -------------------- Utilities ------------------------- //

void setLedRGB(bool red, bool green, bool blue) {
  if (!blue) { digitalWrite(LEDB, HIGH); } else { digitalWrite(LEDB, LOW); }
  if (!green) { digitalWrite(LEDG, HIGH); } else { digitalWrite(LEDG, LOW); }
  if (!red) { digitalWrite(LEDR, HIGH); } else { digitalWrite(LEDR, LOW); }
}

Read the comment to see how it works, AMA if you need help.
HTH
GL :slight_smile: PJ
:v:

Filmed on a Potato
This demo depicts the code for motion / Vibration (if you set it low enough) and for Impact Alerts using the onboard accelerometer & RGB LED the buzzer and display as well as the serial output of the readings are included if you don’t comment out the debug defines flag , If so then no serial output or Display or Buzzer code will be compiled making it very good on power and Tiny in size and if you add some sleep code to it very long battery life.

Hi,
Thank you, that does look great, but I’m not looking to sense vibration or movement, I want to cause it.

Also, I can’t use the expansion board that is FAR too big for what I wanted to do. That said, I am getting the impression that what I wanted to do is possible with the Xiao Seeed boards, which is what I was asking about. I just didn’t want to start buying all the components just to find out it wasn’t possible.

So, thank you.

HI there,
Sure it is, You can do it with just the chip and battery, or a break away Xiao Grove expansion board if the motor needs more juice. Your scenario would be Use BLE to receive a command or button press from the mobile for example to turn on the Motor or Light the LED.
I would look to the Arduino Examples for ArduinoBLE the Central Button LED Control or peripheral code can do what you would need with very little modification,

/*
  Button LED

  This example creates a Bluetooth® Low Energy peripheral with service that contains a
  characteristic to control an LED and another characteristic that
  represents the state of the button.

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
  - Button connected to pin 4

  You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
  nRF Connect (Android), to interact with the services and characteristics
  created in this sketch.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

const int ledPin = LED_BUILTIN; // set ledPin to on-board LED
const int buttonPin = 4; // set buttonPin to digital pin 4

BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service

// create switch characteristic and allow remote device to read and write
BLEByteCharacteristic ledCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
// create button characteristic and allow remote device to get notifications
BLEByteCharacteristic buttonCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);

void setup() {
  Serial.begin(9600);
  while (!Serial);

  pinMode(ledPin, OUTPUT); // use the LED as an output
  pinMode(buttonPin, INPUT); // use button pin as an input

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");

    while (1);
  }

  // set the local name peripheral advertises
  BLE.setLocalName("ButtonLED");
  // set the UUID for the service this peripheral advertises:
  BLE.setAdvertisedService(ledService);

  // add the characteristics to the service
  ledService.addCharacteristic(ledCharacteristic);
  ledService.addCharacteristic(buttonCharacteristic);

  // add the service
  BLE.addService(ledService);

  ledCharacteristic.writeValue(0);
  buttonCharacteristic.writeValue(0);

  // start advertising
  BLE.advertise();

  Serial.println("Bluetooth® device active, waiting for connections...");
}

void loop() {
  // poll for Bluetooth® Low Energy events
  BLE.poll();

  // read the current button pin state
  char buttonValue = digitalRead(buttonPin);

  // has the value changed since the last read
  bool buttonChanged = (buttonCharacteristic.value() != buttonValue);

  if (buttonChanged) {
    // button state changed, update characteristics
    ledCharacteristic.writeValue(buttonValue);
    buttonCharacteristic.writeValue(buttonValue);
  }

  if (ledCharacteristic.written() || buttonChanged) {
    // update LED, either central has written to characteristic or button state has changed
    if (ledCharacteristic.value()) {
      Serial.println("LED on");
      digitalWrite(ledPin, HIGH);
    } else {
      Serial.println("LED off");
      digitalWrite(ledPin, LOW);
    }
  }
}

So from both sides, generating control or receiving LED control is possible. add the motor and BOB is your uncle.
HTH
GL :slight_smile: PJ
:v:

Pretty much anything is possible.

Fantastic, thank you.

I really appreciate all your help/guidance thus far.

My EXP32C3 has just arrived, so I can start testing various setups.

Cheers
Matt