Scroll to Top
OD

Input Devices


Individual Assignment

  • Measure something: add a sensor to a microcontroller board that you have designed and read it

Group Assignment

  • Probe an input device's analog levels and digital signals

Group Assignment


Coming soon

Click here: Probe an input device's analog levels and digital signals



Input Devices



After the stressful machine week, I just wanted to take a long break. I was feeling very lazy to start the next assignment. But when I saw the flexible capacitive sensor, I was very intrigued and wanted to test the same. However, when I finally got the motivation to try out something cool, I started feeling under the weather. I was getting sick and getting better and then again getting sick and getting better. This was going on and off. I took leaves and was left with one day to complete the assignment. So let's see how much I did:



ADXL345

ADXL345 is a Breakout board for the Analog Device's ADXL345 triple axis accelerometer. The module is populated with MOSFET based Voltage level conversion circuitry to enable you to interface different type of microcontrollers (3V3 & 5V). Apart from the above all, necessary components like decoupling capacitors ,filter capacitors ,pull up resistors and LED are also populated on board.

Coming soon

It is ideal for motion and acceleration sensing applications.It is a low-power, 3-axis MEMS accelerometer modules with both I2C and SPI interfaces. The ADXL345 features 4 sensitivity ranges from +/- 2G to +/- 16G. And it supports output data rates ranging from 10Hz to 3200Hz such as the Arduino.

Key features include:
1. Digital Output: SPI / I2C
2. Low Power Consumption
3. Compact Accelemotor / inclinometer
4. 5V/3.3V input support.
5. PCB Board Size: 28mm x 14 mm


ADXL345 Testing

So referring to the schematic, I connected ADXL435 to my board and ran the example code but I had forgotten the flashsize of SAMD11C, so it showed me error! Therefore I referred documentation of previous FAB students. The code was written for MPU6050 so I had to change it for ADXL345.



    #include < Wire.h >

        const int ADXL_addr = 0x53; // I2C address of the ADXL345 accelerometer
        
        void setup() {
            Serial.begin(9600);
            Wire.begin();
            
            // Configure ADXL345
            writeTo(ADXL_addr, 0x2D, 8); // Power Control Register - Set to measure mode
        }
        
        void loop() {
            static unsigned long lastPrintTime = 0;
        
            if (millis() - lastPrintTime >= 5000) { // Print every 5 seconds
            // Read accelerometer data
            int16_t accX = read16BitsFrom(ADXL_addr, 0x32);
            int16_t accY = read16BitsFrom(ADXL_addr, 0x34);
            int16_t accZ = read16BitsFrom(ADXL_addr, 0x36);
        
            // Print accelerometer data
            Serial.print("AcX = ");
            Serial.print(accX);
            Serial.print(" | AcY = ");
            Serial.print(accY);
            Serial.print(" | AcZ = ");
            Serial.println(accZ);
            
            lastPrintTime = millis();
            }
        }
        
        void writeTo(int address, byte reg, byte val) {
            Wire.beginTransmission(address);
            Wire.write(reg);
            Wire.write(val);
            Wire.endTransmission();
        }
        
        int16_t read16BitsFrom(int address, byte reg) {
            Wire.beginTransmission(address);
            Wire.write(reg);
            Wire.endTransmission(false);
            Wire.requestFrom(address, 2, true);
            return (Wire.read() | (Wire.read() << 8));
        }
        
    }
                                                        

Coming soon

These were the values getting read.

Coming soon

Seeed XIAO nRF52840 Sense

Since my final project is a swimming watch make a board with esp 32 module will make the watch size really big. So I found out a suitable board for my final project to interface with the display.

Coming soon

So I referred this documentation to understand the board and followed the steps of board installation. I implemented blink program and additionally, I tried to test the inbuilt sensor which is an accelerometer.


So I referred this documentation and used the code there to test the sensor. That documentation is about using tinyml to sense the human acitivity by one of the instructors Salman Farris.



  // XIAO BLE Sense LSM6DS3 Data  Forwarder 

  #include "LSM6DS3.h"
  #include "Wire.h"

  //Create a instance of class LSM6DS3
  LSM6DS3 myIMU(I2C_MODE, 0x6A);  //I2C device address 0x6A

  #define CONVERT_G_TO_MS2 9.80665f
  #define FREQUENCY_HZ 50
  #define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1))

  static unsigned long last_interval_ms = 0;


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

    if (myIMU.begin() != 0) {
      Serial.println("Device error");
    } else {
      Serial.println("Device OK!");
    }
  }



  void loop() {
    if (millis() > last_interval_ms + INTERVAL_MS) {
      last_interval_ms = millis();
      Serial.print(myIMU.readFloatAccelX() * CONVERT_G_TO_MS2, 4);
      Serial.print('\t');
      Serial.print(myIMU.readFloatAccelY() * CONVERT_G_TO_MS2, 4);
      Serial.print('\t');
      Serial.println(myIMU.readFloatAccelZ() * CONVERT_G_TO_MS2, 4);
    }
  }


So I tried to keep the microcontroller with my watch and tried to immitate the swimming movements with my hands. The values are getting displayed accordingly.



So for my final project, I'm thinking of using tinyml to train the movements of somersault to count the number of laps. I am a little bit familiarised with tinyml since I had attended a workshop about it by one of the instructor Salman Farris before Fab Academy. So the workshop was about using tinyml to sense the movements of the microcontroller. A similar implementation is available in this documentation about using tinyml for sensing human activity.


So here is the library generated during the workshop> Magic Wand


Next, I uploaded this code to the board


  
  /* Includes ---------------------------------------------------------------- */
  #include < Xiao-nRF-MagicWand-LightControl_inferencing.h > //replace the library name with yours
  #include "LSM6DS3.h"

  /* Constant defines -------------------------------------------------------- */
  #define CONVERT_G_TO_MS2    9.80665f
  #define MAX_ACCEPTED_RANGE  2.0f        // starting 03/2022, models are generated setting range to +-2, but this example use Arudino library which set range to +-4g. If you are using an older model, ignore this value and use 4.0f instead
  #define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1))
  static unsigned long last_interval_ms = 0;

  LSM6DS3 myIMU(I2C_MODE, 0x6A);  //I2C device address 0x6A

  static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal

  /**
  * @brief      Arduino setup function
  */
  void setup()
  {
      // put your setup code here, to run once:
      Serial.begin(115200);
      // comment out the below line to cancel the wait for USB connection (needed for native USB)
      while (!Serial);
      Serial.println("Edge Impulse Inferencing Demo");

      if (!myIMU.begin()) {
          ei_printf("Failed to initialize IMU!\r\n");
      }
      else {
          ei_printf("IMU initialized\r\n");
      }

      if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3) {
          ei_printf("ERR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME should be equal to 3 (the 3 sensor axes)\n");
          return;
      }
  }

  /**
  * @brief Return the sign of the number
  * 
  * @param number 
  * @return int 1 if positive (or 0) -1 if negative
  */
  float ei_get_sign(float number) {
      return (number >= 0.0) ? 1.0 : -1.0;
  }

  /**
  * @brief      Get data and run inferencing
  *
  * @param[in]  debug  Get debug info if true
  */
  void loop()
  {
      //ei_printf("\nStarting inferencing in 2 seconds...\n");

      delay(2000);

      //ei_printf("Sampling...\n");

      // Allocate a buffer here for the values we'll read from the IMU
      float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };

      for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 3) {
          // Determine the next tick (and then sleep later)
          uint64_t next_tick = micros() + (EI_CLASSIFIER_INTERVAL_MS * 1000);

          //IMU.readAcceleration(buffer[ix], buffer[ix + 1], buffer[ix + 2]);

          buffer[ix+0] = myIMU.readFloatAccelX();
          buffer[ix+1] = myIMU.readFloatAccelY();
          buffer[ix+2] = myIMU.readFloatAccelZ();



          for (int i = 0; i < 3; i++) {
              if (fabs(buffer[ix + i]) > MAX_ACCEPTED_RANGE) {
                  buffer[ix + i] = ei_get_sign(buffer[ix + i]) * MAX_ACCEPTED_RANGE;
              }
          }

          buffer[ix + 0] *= CONVERT_G_TO_MS2;
          buffer[ix + 1] *= CONVERT_G_TO_MS2;
          buffer[ix + 2] *= CONVERT_G_TO_MS2;

          delayMicroseconds(next_tick - micros());
      }

      // Turn the raw buffer in a signal which we can the classify
      signal_t signal;
      int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
      if (err != 0) {
          ei_printf("Failed to create signal from buffer (%d)\n", err);
          return;
      }

      // Run the classifier
      ei_impulse_result_t result = { 0 };

      err = run_classifier(&signal, &result, debug_nn);
      if (err != EI_IMPULSE_OK) {
          ei_printf("ERR: Failed to run classifier (%d)\n", err);
          return;
      }

      // print the predictions
    // ei_printf("Predictions ");
    // ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
    // result.timing.dsp, result.timing.classification, result.timing.anomaly);
      //ei_printf("\n");
      for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
    // ei_printf("    %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
      if (result.classification[ix].value > .5) {
          ei_printf("%s \n", result.classification[ix]);
      }
      }

      //  if (result.classification[ix].value > .5) {
      //     ei_printf("    %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
      // }
      // }


  #if EI_CLASSIFIER_HAS_ANOMALY == 1
      ei_printf("anomaly score: %.3f\n", result.anomaly);
  #endif
  }

  #if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_ACCELEROMETER
  #error "Invalid model for current sensor"
  #endif



So this code will sense the motion of the microcontroller and identify if it is circle, idle or swish.





Flexible Capacitive Sensor

SAMD11C Flexible Capacitor looked really interesting and fun so I thought of trying it out but with ATTINY1614. Since ATTINY1614 had QTouch embedded in it, I could use it as well.


Here is the redesigned circuit using Attiny1614

Coming soon
Coming soon

Next, I converted Gerber to PNG using this website.

Coming soon
Coming soon
Coming soon

Next, I gave the file for milling.

Coming soon

After the milling and cutting was done, I realised the flexures weren't cut. Turns out with 1/32 bit, the flexure cut weren't being calculated.

Coming soon

So my instructor changed the settings of the bit and did the cutting of the flexures again.

Coming soon

The flexures were done successfully!

Coming soon
Coming soon

Next, I acquired the components. There are 2 things missing in the list: 2x2 header pin and and 6pos header pins

Coming soon

I finished soldering!

Coming soon

Next, I'll start to program the board and test if it works.

Coming soon

Since I am using Quentorres board as programmer, there's a few steps to be followed like I did in week 8. Then for Attiny1614, there's these additional steps:

Coming soon

I tried the blink program and it works!



I referred the documentation but the library used in the code wasn't optimsed for Attiny1614, so I asked ChatGPT for code without library. But nothing was getting displayed on serial monitor. After troubleshooting, it was found that there was hardware errors. So I had inverted RX and TX pins of the header pins to connect it to the chip but I didn't have to do that since the pins were already inverted. But incase of socket, I'll have to invert it.

Coming soon

So I used jumper wires and connected it correctly and checked with a simple code to display hello world. It worked! However I tried to get the capacitance values to be displayed but it wasn't still working with the jumper wires. I'm working on it.

Coming soon

Files