Category: how-to

Controlling two BI2 with Blynk

Controlling more than one body interaction 2 boards is very easy.

At first go to project settings in the Blynk app, go to devices and add a new device.

Then create a new device and press Email. You will get an Email with the auth token.

Add slider widget for the motor and another ZEGBRA widget for controlling the LED. For LED select a new virtual pin, e.g. V10.

You can start with this ready made app:

It should look like this:

 

Then reuse  the code from this blog post.

Change the following:

  • fill-in the auth token which you got per Email
  • change the name of the virtual pin V0 (for the LED) to e.g. V10 (the same name as in the Blynk app)

 

That’s it!

 

Sending motion data to the Blynk app (part 2 of the Blynk tutorial)

In the first blog post we explained the basics of controlling the body interaction 2 (BI2) vibrator development board using the concept of  (virtual) pins. This time we want to send data from the BI2 board to the Blynk app. The BI2 has the MPU-9250 9DoF (9 Degrees of Freedom) IMU (Inertial Measurement Unit) sensor on board. This sensor is a combination of an accelerometer, gyroscope and magnetometer. Especially the accelerometer is important for motion detection. This could be used for controlling the vibrator as show with the body interaction 1 (BI1).

For measuring the motion data we use the asukiaa library. Please search and install the library in the Arduino library manager.

In the program code the library must be included and a MPU9250 sensor object must be defined. Finally we need several variables of the type float.

#include <MPU9250_asukiaaa.h>
MPU9250 mySensor;
float aX, aY, aZ, mDirection, pitch, roll, yaw;

In the setup part of the program we need to tell the MPU9250 how it is connected to the ESP8266 microcontroller. [The MPU9250 IMU is connected by the I2C bus to the ESP8266 microcontroller: the sda pin of the IMU is connected to pin 4, the scl pin to pin 5. The connection between MPU9250 and ESP8266 is managed with the standard Wire library.]

For using the accelerometer and magnetometer we have to initialize the sensor with a begiAccel() call to the IMU library.

Wire.begin(4, 5); //sda, scl
mySensor.setWire(&Wire);
mySensor.beginAccel();
mySensor.beginMag();

We have to tell the program how often data is sent to the app. Therefore we need an important concept in microcontroller programming:

Timer

With the help of the timer we can tell the microcontroller to do a given tasks again and again e.g. after 1000 microsecond. You cannot use the delay function to pass time as this would interrupt the important call to the Blynk.run(); function which is located in the loop part of the program.

First we have to define an object of type Timer.

BlynkTimer timer;

In the setup part we have to say how often what the timer has to do. in this example the timer will call the function myTimerEvent every 1000 microsecond.

timer.setInterval(1000L, myTimerEvent);

In the loop part of the program we have to call the timer to keep things going:

timer.run(); // Initiates BlynkTimer

Now we need the function myTimerEvent what has to be done every 1000 seconds.

void myTimerEvent()
{
  // here add was has to be done
}

First we have to update the sensors (accelUpdate, magUpdate). Then we read out the acceleration data in the X, Y and direction. You can already use this data but they are hard to catch. Therefore we can calculate the pitch, roll and yaw. These are angles from -180° to +180°. The calculation is complicated and I don’t understand it. But with the given formulas you get a very rough approximation which makes the data quite accessible.

void myTimerEvent() {
  mySensor.accelUpdate();
  aX = mySensor.accelX();
  aY = mySensor.accelY();
  aZ = mySensor.accelZ();

  // calculate pitch, roll, yaw (raw approximation)
  float pitch = 180 * atan (aX/sqrt(aY*aY + aZ*aZ))/M_PI;
  float roll = 180 * atan (aY/sqrt(aX*aX + aZ*aZ))/M_PI;
  float yaw = 180 * atan (aZ/sqrt(aX*aX + aZ*aZ))/M_PI;

  // read gyroscope update
  mySensor.magUpdate();
  mDirection = mySensor.magHorizDirection();
}

Finally we send the data back to the Blynk app. Now we use the virtual pins. For the variables pitch we  use virtual pin 2 (V2), for roll V3, for yaw V4 and for mDirection V5. We have to add the following line to the myTimerEvent function.

void myTimerEvent() {
  // send data to app via virtual ports, e.g. virtual pin V2 is set to pitch
  Blynk.virtualWrite(V2, pitch);
  Blynk.virtualWrite(V3, roll);
  Blynk.virtualWrite(V4, yaw);
  Blynk.virtualWrite(V5, mDirection);
}

Now the data are continously sent to the Blynk app. To visualize the data we add the widget SuperChart.

For each variable we have to define the input (virtual) pin. For pitch we use the virtual pin V2. In addition we define the color and style of the graph and more.

 

Finally the super graph shows us the date from the accelerometer which are updated every second.

First part of the tutorial (setup Arduino, setup Blynk, LED and motor control) is here

Here is the complete code:

 

/*************************************************************
bodyinteraction.org
sample program for reading MPU data, setting LED color and motor speed
*/
#define BLYNK_PRINT Serial
// include this library in the Arduino library manager
#include "FastLED.h"

// How many leds in your strip?
#define NUM_LEDS 1
// LED data pin is connected to pin?
#define DATA_PIN 14

// Define the array of leds
CRGB leds[NUM_LEDS];
int wave;

// include this library in the Arduino library manager
#include <MPU9250_asukiaaa.h>
MPU9250 mySensor;
float aX, aY, aZ, mDirection, pitch, roll, yaw;

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "Your Auth Token XXXXXXXXXX";

// Your WiFi credentials.
char ssid[] = "YOUR SSID   XXXXXXXXXXXXXX";
char pass[] = "YOUR Password XXXXXXXXXXXX";
BlynkTimer timer;

void myTimerEvent()
{
  // read acceleration data
  mySensor.accelUpdate();
  aX = mySensor.accelX();
  aY = mySensor.accelY();
  aZ = mySensor.accelZ();
  // read gyroscope update
  mySensor.magUpdate();
  mDirection = mySensor.magHorizDirection();
  // calculate pitch, roll, yaw (raw approximation)
  float pitch = 180 * atan (aX/sqrt(aY*aY + aZ*aZ))/M_PI;
  float roll = 180 * atan (aY/sqrt(aX*aX + aZ*aZ))/M_PI;
  float yaw = 180 * atan (aZ/sqrt(aX*aX + aZ*aZ))/M_PI;
  // send data to app via virtual ports, e.g. virtual pin V2 is set to pitch
  Blynk.virtualWrite(V2, pitch);
  Blynk.virtualWrite(V3, roll);
  Blynk.virtualWrite(V4, yaw);
  Blynk.virtualWrite(V5, mDirection);
}

BLYNK_WRITE(V0) // set RGB color values which are transmitted from the app as V0 (virtual pin 0)
{ 
  int i = param[0].asInt();
  int j = param[1].asInt();
  int k = param[2].asInt();
  leds[0].setRGB(j,i,k);
  FastLED.show();
}

void setup()
{
  Serial.begin(115200);
  FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);

  Wire.begin(4, 5); //sda, scl
  mySensor.setWire(&Wire);
  mySensor.beginAccel();
  mySensor.beginMag();

  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000L, myTimerEvent);
}

void loop()
{
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
}

 

Please feel free to comment or write to jacardano@gmail.com

Programming the body interaction 2 (BI2) with Blynk part 1

This in an intro to using and programming the BI2 with the Blnyk app. Read here how to set up Arduino. For a more general basic intro (based on the body interaction 1 board) read here.

Pins

The communication between app and BI2 microcontroller is realized by pins. The idea is very easy: Each widget in the Blynk app is connected to a physical pin of the microcontroller. Every microcontroller has several pins where you can connect other electronic parts like a LED or a vibration motor. For each pin you have to configure if it is a output or input pin. Output pins are for controlling actuators, like LED, motor or display. Input pins are connected to sensors, like buttons, temperature sensors, acceleration sensor.  In addition each pin can be digital, analog or virtual.

Digital output pins can only set the actuator to on or off e.g. turning the LED on or off. Analog pins can set the actuator to a specific value in a given range. Usual this in done in the range [0..255] or [0..1023]. For a motor 0 will set the motor off, 50 may be make the motor move very slowly and 255 will be full speed. An analog output pin is sometimes called PWM. (PWM is a method to simulate an analog signal with a sequence of digital on/off signals.)

Digital input pins can read the position of a button (on/off). Analog input pins can read a value in a given range, e.g. the acceleration in the X-axis or the temperature.

So what you have to do to connect a widget to a pin? Just set the widget (e.g. on/off switch widget) to the pin you want to set on/off (e.g. a pin which is connected to a LED). That’s all. No programming required. All you need is this small program which must be uploaded to the microcontroller with the Arduino IDE.

The body interaction 2 use the ESP8266 microcontroller. There are 16 pins, all could be used as digital or analog, input or output. But only pin 12 and 13 are free to use (the rest if for internal communication). Pin 14 is connected to the LED WS2821B.

The Arduino sketch

The first 3 lines are for configuring Blynk and using two libraries. The 3 variables auth, ssid and pass are defined. (The variables are from thy type char (=character) and in this case it is not only one character but an array which you can see by the “[” and “]”. Here you have to add your AUTH token from the Blynk app, and SSID and password from your local WLAN/WIFI.

#define BLYNK_PRINT Serial 
#include <ESP8266WiFi.h> 
#include <BlynkSimpleEsp8266.h> 

char auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXX"; 
char ssid[] = "XXXXXXXX"; 
char pass[] = "XXXXXXXX";

Each Arduino program consists of a setup and a loop procedure. The setup is called only one time when the microcontroller is started (or connected to a battery). It is used to initialize the microcontroller, in this case Blynk is started. The loop will be called indefinitely and all statements are executed in the given order. To get Blynk running you have to call Blynk again and again (“Blynk.run();”). According to the Blynk manual, you should not add a delay() function here, because this could disturb the communication between the app and the microcontroller.

void setup() { 
  Blynk.begin(auth, ssid, pass); 
} 

void loop() { 
  Blynk.run(); 
}

Virtual pins

So far communication is only possible with physical pins. But how can you exchange other information? Maybe you want to tell the microcontroller to “shut up immediately”,  or you want to play a given vibration pattern like a sinus curve. For this you can use “virtual pins”. (IMHO there is no reason to call this mean of data exchange “virtual” and it is has nothing to do with a pin. You can call it a variable or channel for data exchange.) The zeRGBa widget is a good example. The color of the LED is controlled by 3 values, the amount of red, green and blue color. This 3 values can be connected to one virtual pin (“V0”) and then they will be transmitted to the microcontroller. To change the color of the LED you have to program the microcontroller  to read out the amount of each color and set the LED to the appropriate value.

We will demonstrate virtual pins with the LED. The WS2821B LED is connected to pin 14, but you cannot control the LED directly by setting the pin to a given value. This is done by a library which controls the LED.

First we have to include the library, we use FastLED.

#include "FastLED.h"

Then  we have to tell how many LEDs we have (you can put several of them in a chain). The BI2 has only one on board (but you can add more).

#define NUM_LEDS 1 // number of LEDs

The you have to tell to which physical pin the LED is connected (14). Finally you have to set up a (instance of an) object “CRGB” for the LED where all relevant data is hidden.

#define DATA_PIN 14 // pin for LED 
CRGB leds[NUM_LEDS]; // define the array of leds

Now comes the more difficult part. The zeRGBa widget has 3 values (one for red, one for green, one for blue) and all are put in the virtual variable V0.

We have add a new function called “BLYNK_WRITE(V0)”. To get the first value we have to read out “param[0]”, for the second “param[1]” etc. We want to store this first value in a variable “i” of the type integer. To assure that param[0] is also from the type integer we add “.asInt()”. The value for red is put in variable i, green in j and blue in k.

BLYNK_WRITE(V0) {
  int i = param[0].asInt();
  int j = param[1].asInt(); 
  int k = param[2].asInt();
}

Now we have to tell the function BLYNK_WRITE what to do with the values i, j an k. This is done by using the method setRGB which is attached to the LED (which is number 0)

leds[0].setRGB(j,i,k);

Now we can make changes to other LEDs (if we have more than one). If you are ready you have to tell the LED to show the new color.

FastLED.show();

In addition a new statement has to be added to setup the LED within the setup part.

void setup() { 
  FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
  [...]

Now we can put everything together the script will look like this:

/*************************************************************
Controling the body interaction 2 board with the Blynk app
*/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// Auth Token infor the Blynk App.
char auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";

// Your WiFi credentials.
char ssid[] = "XXXXXXXX";
char pass[] = "XXXXXXXX";

// Library for controlling the WS2821B (Neopixel) LED or LED strip
#include "FastLED.h"
#define NUM_LEDS 1 // number of LEDs
#define DATA_PIN 14 // pin for LED
CRGB leds[NUM_LEDS]; // define the array of leds

// This function set the LED color according to the selected RGB values in the app.
// RGB values are controlled in the app with zeRGBa widget
// values are stored in the virtual pin V0
// V0 consists of 3 values for Red, Green, Blue
BLYNK_WRITE(V0) // set LED RGB color values
{
  int i = param[0].asInt();
  int j = param[1].asInt();
  int k = param[2].asInt();
  leds[0].setRGB(j,i,k);
  FastLED.show();
}

void setup()
{
  // init LEDs
  FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);

  // connect to Blynk
  Blynk.begin(auth, ssid, pass);
}

void loop()
{
  Blynk.run();
}

Do you like this, do you need this, do you understand this? Tell me jacardano@gmail.com

BI2 – building a silicone sex toy

Now let’s build the first ESP8266 vibrator. I use the reliable design from this blog post and the new BI2 board. The new BI2 board can be controlled from any smart phone or computer.

As the BI2 board is round there is no need to build a case for the PCB and the LiPo. The easist way is to glue the battery directly on the ESP8266. Connect the battery and one or more vibration motors with the BI2 board.

 

The form consists of two parts which are fastened together with tinker wire. Before you have to insert the board with the vibration motor(s) and the battery. Therefore I used a handle. The handle could be put on top of the form. Then fix a USB connector to the handle. Plug in the BI2 board. Fasten the second half of the form.

Very important: The USB micro connector on the board must be protected from the silicone. When silicone flow between USB plug and connector it will be impossible to pull out the plug. I use wax to seal the USB micro connector. Read more here.

 

Now pour in the silicone, wait for some hours. And open softely the form.

 

Remove the overhanging silicone.

Here ist the Link to Tinkercad where you can edit the form and download STL files for your 3D printer: Download from Tinkercad: formhandle. Download ready to print zipped STL files.

Now build YOUR personal sex toy. Here you find the code for the ESP8266 as well as an IOT server application for quantifying your sex and remote control.

BI2: ESP8266 Vibrator Development Board – becoming colourful

The second version of the development board – I will call it BI2 from now on –  has some improvements:

  • I used more components of the original design (Adafruit Feather Huzzah) instead of comparable (and cheaper) Seeedstudio Open Part Library components. The reason for this is easy. The Adafruit design is reliable and approved. No need for designing your own circuits, no risk to fail. (But also no fun in inventing new circuits.)
  • I added LED light – the WS2812B – which is a  colourful LED (16 Mill. colours). They are commonly known as Adafruit Neopixel – a strip or a ring of individual programmable LEDs.
  • The diameter is smaller the first version.
  • It can drive three motors. (When you use the LED then only two motors can be driven.)

Here are some impressions of the board:

 

As you can see I had to wire the LED by hand. The reason for this is that I used GPIO16 which does not work at all. So I wired the LED to GPIO0 which can be used for testing only. The only free GPIOs are 12, 13 and 14.

 

 

 

 

 

 

 

Basic Node for the Internet of Sex Toys – part 3: software

This the third part of the tutorial which has the following parts:

part 1: Basic Node for the Internet of Sex Toys

part 2: Molding the Basic Node

part 3: Software for the Basic Node

For the basic node a simple software realizes all features like Mqtt communication, Web server, basic web user interface, reading data from the accelerometer. Please use the code at github and send request over github. Now the imported parts of the code are explained.

To communicate with the IOT Mqtt is used (read more here). This is a fast protocol for data transmission. Therefore we need a Mqtt server. You can install one on your local computer or use a cloud-based Mqtt server. We use the free CloudMqtt. The following variables must be initiated with the data  of your server. Please get your own account at CloudMqtt or use my server (but don’t spam it, please). Please remember: Transmission is not encrypted, everybody can read it.

const char* mqtt_server = "m12.cloudmqtt.com";
uint16_t mqtt_port = 15376;
const char* mqtt_user = "nvcuumkf";
const char* mqtt_password = "C-X6glwisHOP";

We have now  7 different modes. In each mode the basic node behaves different.

const int offMode = 0;
const int maxMode = 1;
const int sinusMode = 2;
const int motionMode = 3;
const int constantMode = 4;
const int listenMode = 5;
const int listenAndMotionMode = 6;

In off mode the basic node is off, in max mode the vibration is maximum. In sinus mode the vibration speed is altered according to a sinus curve.

Web user interface of the basic node

In motion mode the vibration changes according to the movement of the basic node. When moved fast the speed goes up, when moved slowly or movement stops, the speed goes down. In constant mode any vibration speed can be set to any strength. This feature is only available by Mqtt messages eg. from the IOT node-RED user interface. The listen mode is still experimental. In this mode the speed will be changed by OTHER basic nodes. Finally in the listenAndMotionMode the speed is changed by movements of the basic node and by other nodes. This feature was already available with the body interaction 1 development board as standard mode!

The basic node starts a web server (see image). A web page is generated which build up the user interface. There are buttons for every mode. In addition the speed and the battery power is displayed. This is done in this function:

void generateWebpage() {

The next lengthy procedure is this:

void mqttCallback(char* topic, byte* payload, unsigned int length) {

This is a call back function which is executed whenever a Mqtt message comes in. It parses the Mqtt message which is in the popular JSON format. The commands which are communicated within JSON are explained here. In principle there is a command for every mode, when the command “set mode to off” is send the mode is set to offMode.

In the setup() part of the code you will find a lot of lines like that:

httpServer.on("/MOTOR=MAX", []() {

They corresponds to the generateWebpage() function. When say the max button on the web page is pressed than the affiliated httpServer function is executed. So for every button on the webpage you need a corresponding httpServer function to implement the functionality. In this case (MOTOR=MAX) the mode is set to the constant speed maxMode.

Finally in the loop section of the code the following functions are implemented:

  • reading the accelerometer data
  • change the vibration motor speed according to the mode
  • generate a new JSON message which is send out via Mqtt
  • do the timing

Not mentioned is the OTA (over the air update) function, which is integrated in the code.

Node-RED

For controlling the toy via the internet you can use node-Red. You can find the code at github via this link.

The flow is explained here and here.

 

Basic Node for the Internet of Sex Toys – part 2: 3d printed form, assembly, molding

In this series of posts we describe how-to make a vibrating sex toy which is part of the Internet of Things.

part 1: Basic Node for the Internet of Sex Toys

part 2: Molding the Basic Node

part 3: Software for the Basic Node

In part 2 we describe how-to make a mold form for the basic node. We need three forms:

  • the mold form which consists of two parts
  • the inlay which protects the electronics of the basic node
  • a “hanging” for the inlay

 

 

 

We used Tinkercad to construct the parts. The molding form is based on Tinkercad’s banana form. You can edit and share them from your browser:

Inlay: https://tinkercad.com/things/h5fFOBqlmjw

Hanging: https://tinkercad.com/things/jUxc2oAamww

Form: https://tinkercad.com/things/6HS3XScOsCM

Instructions

Print out all forms. The STL files are available at Thingiverse. You might want to use XTC or similar for smoothing the inner part of the mold form.

Assembling the Inlay

We use the inlay to protect the electronics.

Simply put the electronics inside so that the upper body of the switch is on the same level as the upper inlay. We use hot glue to fix the basic node.

Then fix the receiver coil of the wireless charging module on top of the inlay. The next step is to fix the hanging at the inlay.

Now fix the LiPo battery on the bottom side of the inlay using hot glue or similar. Fix the wires. Finally you might fix the wires of the vibration motor next to the middle of the LiPo battery.

Use tinkering wire to fix both parts of the molding form.

Put the inlay in the form. Fix the hanging with a tape or similar. The motors shouldn’t touch the inner part of the form.

Now prepare the silicone. We use Shore A 45 silicone (approx. 250 ml) from Silikonfabrik.de. It is hard but still a bit flexible. You may add color, too. You have about 10 minutes to stir the silicone and poor it in the form.

After some hours you can remove the form. As you can see there is overhang which make removing the form very hard. The form could break when removing. Better preparation of the form (eg rasping) could improve the results.

If the blue LED of the Wemos board is still active you were successful.

Now you need a charging station. The construction is shown here. It is also possible to connect the sender (or transmitter) module with a 5V power source (eg. from the USB port). Just put the bottom of the molded basic node on the sender coil.

 

In the next part we introduce an updated version of the software including over the air update and WiFi management.

%d bloggers like this: