Skip to content

Week 9 - Machine Design Week


The week to make a machine. A real machine. Strings attached and everything. We do it together as a group. Loes, Nadieh, Nicole and me.

Here you can see us deliberating.

Assignments - Learning Outcomes

Mechanical Design (part 1 of 2)

# Assignment Fin
1 Design a machine that includes mechanism + actuation + automation 1
2 Build the mechanical parts and operate it manually. 1
3 Document the group project 1

Machine Design (part 2 of 2)

# Assignment Fin
4 Actuate and automate your machine. 1
5 Document the group project 1
6 Document your individual contribution. 1

Spirals - Have you?

Spirals Description Done
A Documented the machine building process to the group page 0
B Documented your individual contribution to this project on your own website 1
C Linked to the group page from your individual page as well as from group page to your individual pages 0
D Shown how your team planned and executed the project (Group page) 0
E Described problems and how the team solved them (Group page) -
F Listed future development opportunities for this project (Group page) -
G Included your design files (Group page) 0
H Optionally included an aprox. 1 min video (1920x1080 HTML5 MP4) + slide (1920x1080 PNG) (Group page) 1

Group Page

Sensor research

For my part of the job I am in charge of the sensors.

The aim is to be able to detect the following:

  • Are there people in the room?
  • How many people are there, approximately.
  • Is there light in the room
  • how much light is there in the room

Henk showed us a couple of sensors that could be interesting to use in this project.

These are the following sensors and their (for us interesting) capabilities:

Name Shorthand Detects people Detects nr. of people
HC-05 (ZG-B23090W) Bluetooth 2.0 EDR BT Module 1 0
ESP32 ESP32 1 1
RCWL-0516 Radar Radar 1 0
D-SUN PIR Sensor PIR 1 0

NOTE The phototransister can be used for the light as that is the only, best and no questions further asked option.

Testing the |HC-05 (ZG-B23090W) Bluetooth 2.0 EDR|

I connected the BT Module to my Fabschoolino using jumper wires. It powers on and a little LED starts blinking.

I can find the device on my Mac, but not on my iPhone. When I want to connect to it on my mac it requires a password. The default 0000 does not work. Using 1234 does work. I brute-forced myself in so to say.

As I now want to program the board, I need to connect it to a programmer. For this I use the Fabschoolino; basically an Arduino UNO clone made by Waag. The steps I follow are from the tutorial also mentioned above.

the reason I am doing this (also to remind myself) is twofold

  • my fellow student Loes would prefer to use Arduino
  • I get a change to experiment with two boards

Following the tutorial I connect my board to the fabschoolino:

All lights are on and I can see the serial boards of both boards in my arduino interface.

Using the /cu.SLAB_USBtoUART port I successfully upload the following sketch to my Fabschoolino

//  Sketch: basicSerialWithNL_001
//  Uses hardware serial to talk to the host computer and software serial 
//  for communication with the Bluetooth module
//  Intended for Bluetooth devices that require line end characters "\r\n"
//  Pins
//  Arduino 5V out TO BT VCC
//  Arduino GND to BT GND
//  Arduino D9 to BT RX through a voltage divider
//  Arduino D8 BT TX (no need voltage divider)
//  When a command is entered in the serial monitor on the computer 
//  the Arduino will relay it to the bluetooth module and display the result.

#include <SoftwareSerial.h>
SoftwareSerial BTserial(8, 9); // RX | TX

const long baudRate = 38400; 
char c=' ';
boolean NL = true;

void setup() 
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");

    Serial.print("BTserial started at "); Serial.println(baudRate);
    Serial.println(" ");

void loop()

    // Read from the Bluetooth module and send to the Arduino Serial Monitor
    if (BTserial.available())
        c =;

    // Read from the Serial Monitor and send to the Bluetooth module
    if (Serial.available())
        c =;

        // Echo the user input to the main window. The ">" character indicates the user entered text.
        if (NL) { Serial.print(">");  NL = false; }
        if (c==10) { NL = true; }


In theory I should now be able to send messages through the serial port to the BT module and receive that message on another device that is connected to the BT module. But it appears I have to do some more steps.. I have to put the HC-05 into AT command mode.

To enter AT mode using 38400 baud rate; – power off the module, – press and hold the small button switch, – re-apply power while holding the button switch closed, – when you see the LED come on, release the button switch.

When in AT command mode the LED flash rate will change to 1 second on, 1 second off (or maybe a little slower). Source

Most steps are easy. I am not sure what to do with the 38400 baud rate. Let's see where this leads us...

I seem to be able to communicate with the module. Do not the settings in the bottom-right corner:

Now that we have a connection... we need to

  • Get this BT module into listening mode
  • Get it to register BT devices nearby
  • Output to the Arduino if it has found BT devices as an integer.
  • OUtput to the Arduino how many BT devices it has found as an integer.

But when I start reading the HC-05 datasheet, I feel I have wasted a lot of time. Already in the introduction it states the following:

HC-05 embedded Bluetooth serial communication module (can be short for module) has two work modes: order-response work mode and automatic connection work mode. [...] When the module is at the automatic connection work mode, it will follow the default way set lastly to transmit the data automatically. When the module is at the order-response work mode, user can send the AT command to the module to set the control parameters and sent control order.

I do not need my module to respond to any order and it also does no need to make connections... Preferably not so.

So I guess I am back at square one. Time to test the ESP32...

Testing the ESP32

The ESP32 has both bluetooth and wifi on board. The interesting part of this board is that is also support BLE, which is a low power version of bluetooth.

BLE is a low power wireless communication technology that was developed for battery power applications which can be used to communicate among devices over a short distance. Some of the devices you use every day have Bluetooth built into it like your smartphone, your smartwatch, wireless earbuds, wireless speakers, smart home devices, and more embedded Bluetooth to communicate or to get location data.


There are ready available tutorials, code and instructions for turning an ESP32 into a BLE based proximity sensing device. And I used the code available at for enabling mine.

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#define LED 2 // I added this line to define the LED that should blink when a device is detected

String knownBLEAddresses[] = {"b4:c2:6a:1b:53:99"};
bool device_found;
int scanTime = 5; //In seconds
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++)
        //Uncomment to Enable Debug Information
        if (strcmp(advertisedDevice.getAddress().toString().c_str(), knownBLEAddresses[i].c_str()) == 0)
          device_found = true;
          device_found = false;
      Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
void setup() {
  Serial.begin(115200); //Enable UART on ESP32
  Serial.println("Scanning..."); // Print Scanning
  pinMode(LED, OUTPUT); //make BUILTIN_LED pin as output
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); //Init Callback Function
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100); // set Scan interval
  pBLEScan->setWindow(99);  // less or equal setInterval value
void loop() {
  // put your main code here, to run repeatedly:
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
  for (int i = 0; i < foundDevices.getCount(); i++)
    BLEAdvertisedDevice device = foundDevices.getDevice(i);
    int rssi = device.getRSSI();
    Serial.print("RSSI: ");
    if (rssi > RSSI_THRESHOLD && device_found == true)
      digitalWrite(LED, HIGH);
      digitalWrite(LED, LOW);
  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory

As soon as this sketch is uploaded to the ESP32 (a nice introduction to this board can be found here) the LED started blinking fanatically. And when I opened the serial monitoring port in Arduino I saw a waterfall of detected BT devices.

Taking a sample of that data and cleaning it up a bit gave me at least 22 unique Bluetooth devices where within range of the device. Among them I could identify my own Garmin watch and that of a fellow student.

Using the Wireshark OUI lookup tool I could establish the two Garmin devices as indeed correctly detected. Sadly I could not lookup any of the other MAC addresses for some reason and I will have to investigate if there is nothing fishy going on here.

Whenever advertising BLE, iOS devices will automatically rotate the advertisement packets' MAC address after an unspecified period and conditions. The exact conditions and frequency in which this happens is undocumented, proprietary, and subject to change at any time by Apple. There is no reliable way to predict when an iOS device will rotate the MAC of an ongoing BLE advertisement, although casual testing shows it often remains stable for minutes at a time.


Thoughts so far

More research will be needed to see if and how this can impact our goal of detecting how many people there are (approximately) in a room.

Other shortcomings are that many people will have more then one BT device on them (Watch, Smartphone, Laptop, Tablet etc.) and that there is the odd paradise bird that has none (Henk).

Continuing testing.

I found the page of last years student Yuki Oka who also uses BT proximity to turn on a lamp.

There is also a video tutorial with code to make a BT detection possible.

Climbing the Programming Mountain.

After several days watching youtube tutorials and reading datasheets and other manuals I come to the conclusion that in theory I have all the needed steps figured out. The part that is missing is tying all the parts together. And that involves mostly, or exclusively, programming.

I can't code. That is the main issue for now. I have not written a single line of code in my life. Henk claims that all great coders start by copying code from others. So that is what I will have to do as well. The problem has now shifted from 'writing' code to 'reading code'. As I will need to understand what people have coded in order to be able to copy the right bits and pieces.

To make break it down, I will write down in, as detailed steps as possible, the pieces of code I think I will need to achieve my goal. I will use the little I understand from C++ so far to structure these steps.

My first steps in programming.

  • I made some pseudo code and followed an online tutorial. This resulted in this piece of garbage
  • Then Erwin helped me in an online pad to create something that was much closer to what I needed.
  • Together with the sketch by nkolban, this resulted in some code that finally started to look like something that worked

An important discovery was that the internal LED of the ESP32-WROOM bij AZ-Delivery does not want to stay on. As soon as I switched to an external LED (on advice of Nadieh) it all started to make sense.

I cna now make the light go on and off depending on the amount of LEDs found.

Next steps to make this works

In the meanwhile the other Loes, Nadieh and Nicole are working the light, motor and mechanics.

My next steps are: - Define 5 classes of LED blinks (depending on how many BLE we see, we blink differently) - Get the phototransitor to work - Use boolean functions to make the machine wait untill a movement has ended before it starts a new one. - Could also use a 'change-requirement'. This means that relative to the last scan, in a new scan there needs to be a change in the number of LED of at least n.

Erwin helped me to make some code. So I have a blessed position to start with. This is what I have now:

  if (BLEnumberDevices = 0) {
   // LampState1
   ledcWrite(PWM_CHANNEL, 0); // off
  if (BLEnumberDevices > 0 && BLEnumberDevices < 2) {
   // LampState2
   ledcWrite(PWM_CHANNEL, 63); // lamp op 255/63 = 25%
  if (BLEnumberDevices > 1 && BLEnumberDevices < 4) {
   // LampState3
   ledcWrite(PWM_CHANNEL, 127); // lamp op 255/127 = 50%
  if (BLEnumberDevices > 3 && BLEnumberDevices < 7) {
   // LampState4
   ledcWrite(PWM_CHANNEL, 191); // lamp op 255/191 = 75%
  if (BLEnumberDevices > 6) {
   // LampState5
   ledcWrite(PWM_CHANNEL, 255); // lamp op 255/255 = 100%

Five groups is great. But I don't want the LED to fade to indicate in which group we are. I want the LED to blink and thus show how many BLE's are connected. So I need to

  1. find the code online that makes an LED blink.
  2. translate the number of BLE's found to blinks

To solve 'a' I started with code I got from this blog by Uri Shaked:

#define LED_BUILTIN 26      // Connect the LED to pinout 26

void setup() {

void loop() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

This resulted in a very funky, but erratic blinking of the LED. So I added this piece of code to the end.

  digitalWrite(LED_BUILTIN, LOW);

INTERLUDE While I was working with this code. I got plagued by a board that suddenly didn't want to function anymore.

According to this article it helps to press the RST button when this happens. Leaves the question unanswered; why does this happen now...? And not all the previous sketch uploads that went by without the press of a button.... I guess we will never know.

This error kept plagueing me throughout this project: sometimes pressing RST helped, sometimes not...

In the end I added a 10uF capicator between EN and GND as per advice of this blog This did help a bit as it brought errors down from every second time I tried to upload, to 1 out of 10. I think the ESP32 is just randonly buggy and I have to learn to life with this...

Most important part:

Electrolytic capacitors have polarity. The white/grey stripe indicates the negative lead and should thus be attached to GND


The LED is now burning less randomly, but it does not blink three times as I want. Or so it seemed, as the blinking goes very fast. So I slowed it down and I added a fourth digitalWrite to make it blink even more.

No success so far. Let's try something else:

I added an extra green LED that I had laying around to see if I could change between the two. Using this code:

    if (BLEnumberDevices <= 13){
      Serial.println("there not so many devices...");
      digitalWrite(LED_RED, HIGH); 
      digitalWrite(LED_GREEN, LOW); 
      delay(1000);              // wait for a second
   else if (BLEnumberDevices > 13){
      Serial.println("There are a lot of BLE devices!");
      digitalWrite(LED_GREEN, HIGH);
      digitalWrite(LED_RED, LOW); 
      delay(1000);              // wait for a second  

Fun fact: at first I forgot to add the LOW stages. In my mind the RED light would turn off when the GREEN light goes on. But of course this does not happen when you don't put that explicitly in your code.

Now by repeating HIGH and LOW stages in multiple loops I am going to try to define at least 10 different states of the lamp

In the current state I have three LED's connected to the ESP32. They light up depending on how many BLE devices are found (RED; less then 10, Yellow; between 10 and 15, Green; 15 or more.)

    if (BLEnumberDevices <= 10){
      digitalWrite(LED_RED, HIGH); 
      digitalWrite(LED_GREEN, LOW); 
      digitalWrite(LED_YELLOW, LOW); 
      delay(500);              // wait for a second
   else if (BLEnumberDevices > 10 && BLEnumberDevices <=15){
      digitalWrite(LED_YELLOW, HIGH);
      digitalWrite(LED_RED, LOW); 
      digitalWrite(LED_GREEN, LOW); 
      delay(500);              // wait for a second  

      if (BLEnumberDevices > 10 && BLEnumberDevices <=15){
      digitalWrite(LED_YELLOW, HIGH);
      digitalWrite(LED_RED, LOW); 
      digitalWrite(LED_GREEN, LOW); 
      delay(500);              // wait for a second
   else if (BLEnumberDevices > 15){
      Serial.println("A LOT");
      digitalWrite(LED_GREEN, HIGH);
      digitalWrite(LED_RED, LOW); 
      digitalWrite(LED_YELLOW, LOW);
      delay(500);              // wait for a second  

Now I want to alternate the states of the LEDs themselves. These are now my definitions

#define SPARKFUN 25    // GREEN LED to pinout 25
#define ELWIRE 26      // YELLOW LED to pinout 26
#define MOTOR 27       // RED LED to pinout 27

So when a different amount of BLE devices is found, all three OUTPUT DEVICES should do something different.

After some consultation with Henk, I found that the best way to do this is to use functions. A function encapsulates an operation I want to use a lot. An example of a function could be something lke this:

int NoBLEyesLight(int BLEnumberDevices)
    if (BLEnumberDevices <= 10){
      digitalWrite(SPARKFUN, LOW); 
      digitalWrite(ELWIRE, LOW); 
      digitalWrite(MOTOR, LOW); 
      delay(500);              // wait for a second

if this is true. It would mean that, for now, I'd have to make 10 functions. As there are five different ranges of number of BLE devices found and two ranges of light; light or dark.

Research into functions

Functions combine a set of actions and output an action either/or an integer. This is great, as you can break down the parts of your program into functions and then call them, one after the other, in your loop. You use the output of one function as input in another function.

I have defined three functions now.

  1. int GetBLEDevices: this function scans for BLE devices. The output is the number of BLE devices it finds: BLEDevices
  int GetBLEDevices() {
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false); 
  int BLEnumberDevices = foundDevices.getCount();
  Serial.print("BLEDevices: ");
  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory

  return BLEnumberDevices;
  1. int GetLampState: this function defines 5 different ranges. It uses the output of GetBLEDevices and sorts them in five different classes called LampStates. The output is a number from 1 to 5: LampState.
int GetLampState (int BLEDevices) {

 int LampState;

  if (BLEDevices > 1 && BLEDevices <= 7) {
    LampState = 1;
  else if(BLEDevices > 7 && BLEDevices <= 8) {
    LampState = 2;
  else if(BLEDevices > 8 && BLEDevices <= 10) {
  LampState = 3;
  else if(BLEDevices > 10 && BLEDevices <= 13) {
  LampState = 4;
  else if (BLEDevices > 13) {
  LampState = 5;
  else LampState == 0;

  return LampState;
  1. void ChangeLamp: this function uses the input GetLampState to tell the output devices if they should be HIGH or LOW. As this is an action, and not an integer, I use void
void ChangeLamp (int LampState) { // void is als er niks terugkomt, maar een actie uitgevoerd
  if (LampState == 1) {
      Serial.println("NO LIGHT");
      digitalWrite(MOTOR, LOW); 
      digitalWrite(SPARKFUN, LOW); 
      digitalWrite(ELWIRE, LOW); 
  else if(LampState == 2) {
      Serial.println( "RED");
      digitalWrite(MOTOR, HIGH); 
      digitalWrite(SPARKFUN, LOW); 
      digitalWrite(ELWIRE, LOW); 
  else if(LampState == 3) {
      Serial.println("RED & GREEN");
      digitalWrite(MOTOR, HIGH); 
      digitalWrite(SPARKFUN, LOW); 
      digitalWrite(ELWIRE, HIGH); 
  else if(LampState == 4) {
      Serial.println("YELLOW & GREEN");
      digitalWrite(MOTOR, LOW); 
      digitalWrite(SPARKFUN, HIGH); 
      digitalWrite(ELWIRE, HIGH); 
  else if(LampState == 5) {
      Serial.println("RED, YELLOW & GREEN ");
      digitalWrite(MOTOR, HIGH); 
      digitalWrite(SPARKFUN, HIGH); 
      digitalWrite(ELWIRE, HIGH); 

This then all comes together in the loop:

void loop() {  

  BLEnumberDevices = GetBLEDevices();
  LampState = GetLampState(BLEnumberDevices);
  delay(1000);              // wait for a second  

The results of various functions are also printed to the serial monitor. This has the following result:

For now I am happy with this result. It allows me to output integers to three different output devices and that is what we currently need.

INTERLUDE I get tired from the limited capabilities of Arduino IDE. Everyone online seems to use Visual Studio Code with the PlatformIO plugin. So I installed that. Sadly I get an error

Downloading package 'C/C++ language components (OS X)'  Failed. Retrying... Failed. Retrying... Failed. Retrying...Waiting 8 seconds... Failed. Retrying...Waiting 16 seconds... Failed to download
Failed at stage: downloadPackages
Error: connect EBADF
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)

If you work in an offline environment or repeatedly see this error, try downloading a version of the extension with all the dependencies pre-included from, then use the "Install from VSIX" command in VS Code to install it.

So let me try that first now.

I download the latest version of vscode. the option to install an VSIX file is located in the extensions window.

That seems to have worked. Now I will work on the next part of my saga in VSC. /INTERLUDE

Add an LDR

What still is missing in this whole setup, is the LDR input. This sensor should find out how much light there is in the room and my goals is to use this to drive the stepper motor. A gradual light change, should gradually change how open, or closed the flower is. Ideally it opens at night, and closes in the day; as this is just way more romantic then the opposite.

For this part I used code from That went without a hitch.

Playing a little bit with the code reveals that this part is interesting:

if(lightVal - lightInit < 50 )

The higher the number, the darker the LDR thinks it is and the quicker the LED turns on. Now I want to

  1. read the values the LDR outputs in my serial monitor
  2. be able to find out how I can use the values to fade the LED, instead of switching between ON/OFF.

It seems as if I need something called PWM for this.

In simple terms the PWM refers to the pulse with modulation feature of the arduino. In the pwm pins the output signal via a pwm pin will be an analog signal ( at least it behaves like one) acquired as a digital signal from the arduino .It uses the duty cycle of the digital wave to generate the consequent analog value for the signal. source

Also I found out that on the ESP32 "all pins that can act as outputs can be used as PWM pins."

Read the values the LDR outputs in my serial monitor

In order to achieve this I added Serial.begin(9600) to my void setup() and added Serial.println(lightVal); to the void loop(). I also added delay(1000); in order to pause a bit to make the serial write readbale to the human eye.

Find out how I can use the values to fade the LED, instead of switching between ON/OFF.



In Arduino and NodeMCU, we use the analogWrite() function to "write" value between 0 and 254 to the LED pin. But the ESP32 development board does not support the analogWrite() function. So instead of analogWrite(), we will use another function i.e. the ledcWrite() function.

Using this code I was able to et the LED to DIM when the LDR was in a darker place. Also, the values are send to serial and can be read there.

``` const int ledPin = 26; // 16 corresponds to GPIO16 uint16_t dutyCycle; // setting PWM properties const int freq = 15000; const int ledChannel = 0; const int resolution = 12;

void setup(){ Serial.begin(9600); // configure LED PWM functionalities ledcSetup(ledChannel, freq, resolution); // attach the channel to the GPIO to be controlled ledcAttachPin(ledPin, ledChannel); } void loop(){ dutyCycle = (analogRead(25)/10); // I made the output number smaller for legibility in the serial/ Serial.println(dutyCycle); ledcWrite(ledChannel, (dutyCycle)); // changing the LED brightness with PWM delay(15); } ```

Next issue; do the reverse: make the LED shine when lights go down and bring the LED down when other light is present.

I got a bit tired googling for solutions, so I posted my problem to the Arduino forums. Sure enough someone came up with the answer only 20 minutes later.

if you want the LED to be less bright when light decreases, you need to make sure your PWM value is moving in the right direction. if you are on 8 bit PWM, it means that instead of sending the value 'V' you had in the sketch, you need to send the "opposite one" (255 - V).

I previously already observed that my LDR goes to max 4095, so I use that number to define the reverse dutycycle:

dutyCycle = (4095-(analogRead(25)));

I also removed the delay from the code and am pretty happy with the result: a smooth transition from dark to bright when light is dimmed.

The build up.

Making it all come together proved harder then we thought. Nadieh and Loes were trying to bring it all together and I handed my work over to them in good faith that they would be able to figure out how to bring all together. Also because I knew for sure I wouldn't be able to pull that off. Sadly as far as I understood from them, there were several complexities they couldn't overcome. The most important one was that my code ran on an ESP32 and theirs on an Arduino. We weren't able to get the serial output from the ESP32 into the Arduino.

In the end Nadieh connected a light sensor to the lamp so it would at least react to light. But all the work on this page has been in vain as far as this project is concerned. Of course I learned a lot.

My biggest contributions to the final project were the painstakingly wiring of the el-wire to the sides of the leaves and the shooting and editing of the movie you see below.



bipolar hello.stepper.bipolar.44 board components traces interior full makefile video