Many makers sacrifice their social life to play with devices and spend many hours and days making fun things. However, the non-maker do not understand that a robot is something beautiful even if there is a breadboard, components and noise in this tinny thing.
Wearable devices are an opportunity towards the reconciliation between the makers and the rest of the population. By building sexy wearable things, people can understand that things that we build are not some useless toys for big boys :D
The ideaSome lingerie companies are investigating approaches to incorporate IoT technology in their products. However, the majority of those efforts try to find useful application that change the life of the consumer. This link describe some of those efforts.
The Idea behind this project is to have fun IoT Bra to play with. Like chewing gum, just for fun !. You can use the connected Bra because you want to share a funny moment with your boy/girl friend. Dancers may also use it to give wireless interaction capability to their public.
Oops! MKR1000 is 3v (not 5v as i say in the video)
How it worksBefore giving technical details let's look at the interaction model. Figure 1 illustrates in interaction between the Bra and the mobile device.
You can use your mobile device as an access point. Once the access point started, turn on the MKR1000 by connecting the battery. The MKR1000 will get connected to your mobile device. You can then request the control web page from you mobile device (or computer if connected to the same access point) using the IP of the MKR1000.
You can use the serial monitor to get the IP address of the MKR1000. One other way to do that is to use the HotSpotManager App to get the IP of the connected devices to your access point.
Using the IP of the MKR1000, you can request the control web app (ex. http://1.0.0.0/ ). The Figure 2 illustrates how the web application looks like. the color picker is used to choose the RGB value that will be sent to the Bra and displayed using the neopixels.
You need to sew on the components to the Bra. The schematics illustrates the links between the components. Figure 3 illustrates how to put all that in the Bra.
The IC Socket is very useful to sew on the Level-Shifter (3V to 5V) as it allows you to sew on without damaging this useful component.
This component is needed to connect the 5v neopixels to the 3v MKR1000.
I suggest that doing the stitching on the outside or covering the thread on the inside to protect it from shorts from the skin. (Thanks Leslie Birch for the feedback)
The access point credentialsYou have to put your access point credentials on the sketch before uploading it to the board. As illustrated bellow. You need to put your SSID and PASS on the .ino file.
char ssid[] = "yourMobileDeviceAP_SSID"; // your network SSID (name)
char pass[] = "yourMobileDeviceAP_password"; // your network password
The embedded web appThe Bra are controlled a web app that use mobile jquerry. It use also a jscolor as web color picker.
The web app have two behaviors according to the request. If you ask for the root file (ex. http://1.0.0.0/ ), the web app will send the HTML/Javascript that is used for the control. If you ask for the path /neo/R/G/B where R, G, and B are values between 0 and 255 (ex. http://1.0.0.0/neo/110/111/112 ), the web app will update the color on the NeoPixels and send a status as response. The code bellow illustrates this behaviors.
void loop() { WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
digitalWrite(ledpin, HIGH);
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() != 0) {
if(currentLine.indexOf("GET") != -1){
if (currentLine.indexOf("/neo") != -1) {
sendStatus(currentLine,client);
}else {
sendPage(client);
}
break;
}
}
else { // if you got a newline, then clear currentLine:
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
else{
break;
}
}
// close the connection:
client.stop();
Serial.println("client disonnected");
digitalWrite(ledpin, LOW);
}
}
<br/>
void sendStatus(String currentLine, WiFiClient client){
Serial.println("processing the url params from :");
Serial.println(currentLine);
int r = currentLine.indexOf("/");
r = currentLine.indexOf("/", r + 1);
int g = currentLine.indexOf("/", r + 1);
int b = currentLine.indexOf("/", g + 1);
int e = currentLine.indexOf(" ", b + 1);
r = currentLine.substring(r + 1, g).toInt();
g = currentLine.substring(g + 1, b).toInt();
b = currentLine.substring(b + 1, e).toInt();
Serial.println("r=" + String(r) + ", g=" + String(g) + ", b=" + String(b));
for(int i=0;i<NUMPIXELS;i++){
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(r,g,b));
pixels.show(); // This sends the updated pixel color to the hardware.
}
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 201 OK");
client.println("Content-type:application/json");
client.println("Connection: close");
client.println();
// the content of the HTTP response follows the header:
client.print("{NeoPixelsStatus:updated,r:"+String(r)+",g:"+String(g)+",b:"+String(b)+"}");
client.println();
}
void sendPage(WiFiClient client){
Serial.println("Sending Main Page");
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// the content of the HTTP response follows the header:
client.print("<!DOCTYPE html>\n");
client.print("<html>\n");
client.print("<head>\n");
client.print(" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n");
client.print(" <link href=\"http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css\" rel=\"stylesheet\" type=\"text/css\" />\n");
client.print(" <script src=\"http://code.jquery.com/jquery-1.9.1.min.js\"></script>\n");
client.print(" <script src=\"http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js\"></script>\n");
client.print(" <script src=\"http://jscolor.com/release/2.0/jscolor-2.0.4/jscolor.js\"></script>\n");
client.print(" <meta charset=utf-8 />\n");
client.print(" <title>Neo Bling Bra</title>\n");
client.print(" <script>\n");
client.print("\n");
client.print(" $(document).bind('pageinit', function() {\n");
client.print(" $(\"#neocolor\").on(\"change\", function() {\n");
client.print(" var hex = $.trim($(\"#neocolor\").val());\n");
client.print(" var rgburl = \"neo/\"+parseInt(hex.substring(0, 2), 16)+\"/\"+parseInt(hex.substring(2, 4), 16)+\"/\"+parseInt(hex.substring(4, 6), 16);\n");
client.print(" $.get(rgburl, function(data, status){\n");
client.print(" alert(\"Data: \" + data + \"Status: \" + status);\n");
client.print(" });\n");
client.print(" $(\"#footerH3 span\").text( rgburl );\n");
client.print(" });\n");
client.print(" });\n");
client.print(" </script>\n");
client.print("</head>\n");
client.print("<body>\n");
client.print("<div data-role=\"page\">\n");
client.print(" <div data-role=\"header\"><h1>Neo Bling Bra</h1></div>\n");
client.print(" <div data-role=\"content\">\n");
client.print(" <input class=\"jscolor\" id=\"neocolor\" value=\"99CC00\" />\n");
client.print(" </div>\n");
client.print(" <div data-role=\"footer\">\n");
client.print(" <h3 id=\"footerH3\" >Push color <span></span> to the Bra</h3>\n");
client.print(" </div>\n");
client.print("</div>\n");
client.print("</body>\n");
client.print("</html>\n");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
}
Replicate and have fun !!You are ready now to replicate the project. Enjoy and feel free to ask me for more details.
Comments