Bits and Droids logo
Mail icon

Flight sim connected coffee machine

by Bits and Droids | 21-03-2023

This title might sound ridiculous. Nobody asked for it. But I still had to do it. A quick Google search didn't grant me any results so I low key hope that this will be the first, the one, and the only; Microsoft Flight Simulator 2020 controlled Coffee machine.

Receiver module
Receiver module

Now this might all sound very silly but there is actually a valid reason why I did what I did. I get asked a lot of questions wether a component/board works with the Bits and Droids flight sim connector. In theory as long as you can wire it up, code it and it can receive Serial communication you should be able to use any component you'd desire. This silly experiment is just a way of showing that almost anything can be made possible with just a bit of imagination.

At first, I thought it would be wasteful to throw my test batches of coffee down the drain. But after cup number 6 of double espresso, I gave up. I became too tweaky and decided to skip the next test batches to preserve my sanity.

This project runs on 2 ESP32 modules:
- https://amzn.to/3w1Hc7h (affiliate link)

The way it's implemented is that there is 1 dedicated module that receives the data from the connector. There are no components connected to this board whatsoever. The second module has a servo connected to press the button. The board listens for updates and, if the coffee time is triggered, our code pushes the servo forwards.

Debugging the contraption

Now perhaps you don't want an automated coffee maker. But the contraption we've created opens up a realm of possibilities. Wireless modules? Wireless gauges? The sky is the limit!


Sender code

//Add necessary libraries
#include <BitsAndDroidsFlightConnector.h>
#include <esp_now.h>  //To access the esp now functions

#include <WiFi.h>     //To Add Wifi Capabilities on ESP32
BitsAndDroidsFlightConnector connector(false);
bool onGround = true;
bool prevOnGround = true;
bool coffeeTime = false;
//save the MAC Address in an array named broadcastAddress;
uint8_t broadcastAddress[] = {0xB8, 0xF0, 0x09, 0xCC, 0x94, 0xEC}; //MAC address of my receiver

/*define the data types of  the multiple variables structured and
renamed all of it as struct_message*/
typedef struct struct_message {
  char a[32];
  bool landed;
} struct_message;
const byte btnPin = 14;
// Create a struct_message called myData
struct_message myData;

// function called when data is sent to print its status
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}


void setup() {
  //Set the baud rate for serial communication with ESP
  Serial.begin(115200);
  pinMode(btnPin, INPUT_PULLUP);
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);//Starts the wifi

  // Init ESP-NOW and returns its status
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  //call the function OnDataSent after sending ESPNOW data
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  esp_now_peer_info_t peerInfo; //initialize and assign the peer information as a pointer to an addres
  memcpy(peerInfo.peer_addr, broadcastAddress, 6); //copy the value of  broadcastAddress with 6 bytes to peerInfo.peer_addr
  peerInfo.channel = 0;  //channel at which the esp talk. 0 means undefined and data will be sent on the current channel. 1-14 are valid channels which is the same with the local device 
  peerInfo.encrypt = false; //not encrypted
  
  
  //Add the device to the paired device list 
  if (esp_now_add_peer(&peerInfo) != ESP_OK){ 
    Serial.println("Failed to add peer");
    return;
  }
}
 
void loop() {
  connector.dataHandling();
  onGround = connector.getOnGround();
  if(onGround != prevOnGround){
    if(!prevOnGround){
      coffeeTime = true;
    } else{
      coffeeTime = false;
    }
    prevOnGround = onGround;
  }
  myData.landed = coffeeTime;
  // Set values to send
  strcpy(myData.a, "Is it coffee time?"); //save "THIS IS A CHAR" to variable a of my "data" defined earlier
  

  //Send data less than or equal 250 bytes via ESP-NOW and returns its status
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
    Serial.println(coffeeTime);
  }
  else {
    Serial.println("Error sending the data");
  }
  delay(500);
  
}

Receiver code

//#include <LiquidCrystal_I2C.h>
#include <driver/adc.h>
#include <ESP32Servo.h>

//Add necessary libraries
#include <esp_now.h>  //To access the esp now functions
#include <WiFi.h>     //To Add Wifi Capabilities on ESP32


int servoPosition;
const byte potPin = 13;
int value;
Servo servoA;
Servo servoB;
/*define the data types of  the multiple variables structured and
renamed all of it as struct_message*/
typedef struct struct_message {
    char a[32];
    bool e;
} struct_message;
bool lastStateCoffeeTime = false;
bool coffeeTime = false;
const byte ledPin = 14;
// Create a variable struct_message called myData
struct_message myData;

// function called when the data is received and prints it
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.println(myData.a);
  Serial.print("Bool: ");
  Serial.println(myData.e);
  coffeeTime = myData.e;
  Serial.println();
}
 
void setup() {
  //Set the baud rate for serial communication with ESP
  Serial.begin(115200);

  pinMode(ledPin, OUTPUT);
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);  //Starts the wifi
  servoA.setPeriodHertz(50);
  servoB.setPeriodHertz(50);
  servoA.attach(27,500,2400);
  servoB.attach(25,500,2400);
 // Init ESP-NOW and returns its status
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
}
void loop() {
   value = adc1_get_raw(ADC1_CHANNEL_6);
    

  
  value = map(value, 0, 4095,0,180);

  Serial.println(value);
  servoB.write(value);
 
  delay(100);
  if(coffeeTime && !lastStateCoffeeTime){
    digitalWrite(ledPin, HIGH);
    servoA.write(34);
    delay(500);
    lastStateCoffeeTime = true;
    servoA.write(0);
    //servoB.write(45);
  } else if(!coffeeTime && lastStateCoffeeTime){
    digitalWrite(ledPin, LOW);
    lastStateCoffeeTime = false;
    servoA.write(0);
     //servoB.write(0);
  }
}