Smart Cube: De Volgende Generatie Thuisbesturingshub
Onderdelen en benodigdheden
| Arduino 101 | × | 1 |
| LED (standaard) | × | 5 |
| Weerstand 221 ohm | × | 5 |
| Experimenteerbord (standaard) | × | 1 |
| Seeed Base Shield V2 | × | 1 |
| Seeed Grove LCD RGB Backlight | × | 1 |
| Seeed Grove Geluidssensor | × | 1 |
| Seeed Grove Buzzer | × | 1 |
| Seeed Grove Temperatuursensor | × | 1 |
| Keypad | × | 1 |
| Draadbruggen (standaard) | × | 1 |
| 9V batterij (standaard) | × | 1 |
| 9V Batterijclip | × | 1 |
| MDF 20x30 cm (Medium Density Fiber) | × | 1 |
Benodigde tools en machines
- Lasersnijder (standaard)
- Soldeerbout (standaard)
Apps en online services
- Arduino IDE
- Nordic Semiconductor nRF Connect SDK (niet verplicht)
Over dit project
Wat is SMART CUBE?
Smart Cube is een controller voor je slimme huishoudelijke apparaten.
Tegenwoordig wordt het beheren van alle apparaten in ons huis op een slimme manier een vereiste. We hebben iets eenvoudigs en intuïtiefs nodig. Smart Cube kan een oplossing zijn: het is een draagbaar apparaat dat een Arduino 101-board en enkele sensoren bevat die communiceren met de apparaten en actuatoren in je slimme huis.
De innovatie van deze afstandsbediening hangt samen met de innovatie van het Arduino 101-board. Het gebruikt Bluetooth (BLE) om lampen, temperatuur en je tv te bedienen en je kunt het ook synchroniseren met je smartphone. Maar de grootste innovatie is de manier waarop je interageert met Smart Cube met je gebaren door de gyroscoop en de accelerometer. De kubus heeft 6 vlakken en elk bedient een specifieke functie. De functie die je wilt gebruiken wordt gedetecteerd door de gyroscoop die het bovenste vlak herkent. Je kunt bijvoorbeeld de lampen in de kamer waar je bent aanzetten door de kubus met het "licht-vlak" in de bovenste positie te plaatsen. Als je het licht wilt uitschudden, hoef je de kubus alleen maar te schudden.
Als een vlak BOVEN is en het niet beweegt gedurende meer dan 2 seconden, wordt de bijbehorende functie geactiveerd. Deze vertraging is gemaakt zodat je de tijd hebt om de kubus te draaien en te interacteren om het gewenste vlak te vinden zonder per ongeluk andere functies te activeren. Als je de kubus meer dan 2 seconden schudt, wordt de laatst geactiveerde functie gesloten.
Dit project heeft als doel je te helpen een slimme controller te bouwen. Dit apparaat heeft een ontvanger nodig (slimme centrale in de afbeelding) die de data interpreteert en de functies beheert van je slimme huis. De belangrijkste uitgang van de kubus is een BLE-signaal dat op veel manieren gebruikt kan worden: je kunt de kubus verbinden met een smartphone-app (of je eigen maken), of een station met een andere Arduino bouwen dat de BLE-data verzamelt en direct de apparaten in je huis bedient. Omdat er veel gevallen mogelijk zijn, hangt dit deel van je behoeften af. In deze handleiding zien we hoe je een smart cube bouwt en hoe je het kunt personaliseren.

Functies:
De codestructuur is eenvoudig te personaliseren (we analyseren de code later) zodat je kunt beslissen welke functies je wilt bedienen. Dit zijn de functies die ik gekozen heb:

LICHTEN: Dit vlak in BOVEN-positie zet de lampen aan in de kamer waar je bent. Als je de kubus schudt, gaan de lampen uit en wordt een gele led op dit vlak geactiveerd zodat je de kubus in het donker kunt vinden. De communicatie met je lampen gebeurt via de BLE van het 101-board.
TEMPERATUUR: Dit vlak BOVEN activeert (via BLE) de airconditioning als het warm is of de verwarming als het koud is. Het detecteert de temperatuur met een thermische sensor en zet een blauwe led aan als de airco aanstaat (sneeuwvlok) of een rode als de verwarming actief is (zon).
TIMER: Dit vlak BOVEN start een timer die je op het LCD-display ziet. Er is een buzzer die werkt als alarm wanneer de aftelling klaar is. Als je schudt, stop je de timer en zie je de resterende tijd. Wanneer de aftelling eindigt, verandert de kleur van de LCD van blauw naar rood en maakt de buzzer drie geluiden.
TV: Dit vlak BOVEN zet de TV aan. De kubus wordt een afstandsbediening voor je TV. Er is een knoppenpaneel met nummers dat alleen actief is als dit vlak BOVEN is, om ongewenste aanrakingen te voorkomen. Het ingedrukte nummer wordt via BLE naar de centrale controller gestuurd die met je TV verbonden is. Door de kubus te schudden, zet je de TV uit.
GELUID: Dit vlak BOVEN activeert een led wijn helderheid gebaseerd is op het geluidsniveau in de kamer. Het geluid wordt gedetecteerd dankzij een geluidssensor. Als je de kubus schudt, sluit je deze functie. (Als je wilt kun je je eigen functie activeren door in je handen te klappen).
UIT vlak: Als je de kubus niet schudt, is dit vlak een neutrale positie waarin niets verandert. Als je alles wilt sluiten, plaats de kubus met het UIT-vlak BOVEN en schud hem. Deze gebaar is als de home-knop op je smartphone die je indrukt als je snel wilt afsluiten. Er is een rode led zodat je de kubus in het donker kunt vinden.
Verschillen met het concept:
Het oorspronkelijke plan was om ook IR-communicatie te gebruiken om je TV direct met de kubus te verbinden. Omdat de Arduino 101 (voor nu) de bibliotheek die IR-signalen beheert niet ondersteunt, besloot ik de informatie via BLE naar een station te sturen dat deze bibliotheek wel kan beheren (zoals Arduino UNO). Vanwege dit probleem heb ik de radiofunctie (zeer vergelijkbaar met TV-vlak) verwijderd en vervangen door een geluidssensorvlak. Dit vlak kan gebruikt worden om een luid geluid (zoals handen klappen) te herkennen om iets te activeren. De grootste verandering zit in het materiaal van de kubus. Initieel dacht ik het met een 3D-printer te bouwen, maar toen besloot ik een lasersnijder te gebruiken. Op die manier is het makkelijker om een vlak te vervangen als je een functie wilt wijzigen. Je kunt bijvoorbeeld het timer-vlak verwijderen en vervangen door een vlak dat automatisch de voerbak van je kat vult. Omdat het modulair is, hoef je de hele structuur niet opnieuw te bouwen!

Laten we het bouwen:
Volg deze instructies om je eigen smart cube te bouwen. We beginnen met de hardware, eerst de electronica monteren en daarna de lasersnijde behuizing van MDF. Daarna leg ik uit hoe de code werkt en hoe je het kunt personaliseren. Na het uploaden van de code op je Arduino 101 kun je de app downloaden om de BLE-uitgang van de kubus te zien of het direct verbinden met je slimme huis!

Hardware - electronica:
Laten we beginnen met je Arduino 101. Dit is het Fritzing-schema om te volgen:

Monteer de Grove base shield op je board en begin met de verbindingen.


Keypad: je moet de draden in volgorde aan de pinnen verbinden: 10, 8, 7, 6, 5, 4, 2.



LED verbindingen:
Allereerst moeten we de leds voorbereiden:
- Verbind de lange poot van de led (anode) met een 220 ohm weerstand en dan met een rode draad (dit is de kabel om aan de pin te verbinden)
- Verbind de korte poot (kathode) met een witte draad (dit gaat naar de ground)
- Solder de onderdelen en bedek ze met isolatietape
- Verbind alle witte kabels met een enkele witte kabel (deze gaat naar de ground) en solder ze allemaal samen
Verbind nu de rode draden met je Arduino: GROENE led naar pin 9, GELE led naar pin 11, RODE led naar pin 12, BLAUWE led naar pin 13 en de laatste RODE naar pin A2.




Grove sensors:
Sluit de Grove-sensoren aan op de shield (zie schema in bijlagen).
Buzzer naar D3, LCD RGB naar I2C, Temperatuursensor naar A0, Geluidssensor naar A1.

Ok, nu hebben we alle elektrische onderdelen aangesloten. Nu heb je de behuizing nodig.
Hardware - behuizing
Je kunt de tekening van de kubus downloaden om met de laser te snijden. De rode lijnen in de tekening zijn de symbolen van de vlakken, graveer ze alleen. De zwarte lijnen moeten gesneden worden. De interne afmeting van de kubus is 9 cm. De tekening klopt als je 3mm materiaal gebruikt, als je een andere dikte gebruikt moet je het aanpassen (je kunt deze website gebruiken: https://www.makercase.com/).
Het gekozen materiaal is MDF (Medium Density Fiber) maar je kunt gebruiken wat je wilt.
Hier zijn enkele foto's van het lasersnijden:




Nu moeten we het monteren.
Ik heb gekleefd enkele stukjes karton om dikte te maken voor de leds. Op die manier zijn ze uitgelijnd met het oppervlak.



Nu monteren we het keypad. Steek het in het gat en verwijder de beschermfolie, verbind daarna de pinnen weer.



Nu de RGB LCD. Deze past perfect in het gat.


Laten we de batterijconnector voorbereiden:
Ik heb een oude transformatorsteker afgeknipt en aan een batterijclip verbonden. Op die manier besparen we ruimte binnenin de doos.



Op dit moment zou je dit moeten hebben:

Nu hoef je alleen nog de batterij aan te sluiten, de code te uploaden en de kubus te sluiten!
TIP: bevestig het board en de batterij aan de behuizing zodat ze stabiel blijven als je de kubus schudt.

Code
Je vindt de code in de bijlagen. Upload het naar je board met de Arduino IDE (onthoud je software te updaten voor Arduino 101-compatibiliteit).
Ik heb bijna elke regel van de code gecommentarieerd om het zo begrijpelijk mogelijk te maken. Wees niet bang voor de 500+ regels, de structuur is niet zo ingewikkeld.
Aan het begin staan de bibliotheken en alle variabelen declaraties.
In dit deel zit ook de definitie van BLE services en characteristics. Ik gebruikte de Automation IO-service. Ik gebruikte de Digital-characteristic voor lichten en temperatuur (dit gebruikt 2 bits, dus 4 mogelijke gevallen om te coderen) en de Analog voor TV (om alle codes van het keypad te sturen).
Dan de setup. Dit deel wordt alleen één keer bij het begin uitgevoerd. Hier initialiseren we de componenten als in- of uitgangen en initialiseren we de BLE en de gyroscoop van het 101-board.
Het hoofddel is de loop. Het is verdeeld in vier delen:
- 1 Het eerste deel is gekopieerd van de Arduino-website tutorial: (https://www.arduino.cc/en/Tutorial/Genuino101CurieIMUAccelerometerOrientation) dit deel wordt constant uitgevoerd en geeft de oriëntatie van het board terug.
- 2 Het tweede deel activeert een vlak alleen als het in de bovenste positie is gedurende meer dan twee seconden. We gebruiken de millis-functie om de tijd te tellen. Wanneer de positie verandert, onthoudt het de millis-waarde en als de oriëntatie hetzelfde blijft, na een interval (2 sec), gaan we in een if-zone waar het geselecteerde vlak true wordt (voor het 4e deel).
- 3 Het derde deel wordt alleen geactiveerd als de kubus geschud wordt met een bepaalde intensiteit en gedurende meer dan 2 seconden. De laatst geactiveerde vlakfunctie wordt gesloten en het vlak wordt op false gezet. Als het vlak false is, kan het niet in het 4e deel komen.
- 4 Het vierde deel is alleen voor true vlakken. Hier zit de kern van de functies van de smart cube. In dit deel worden constant alleen de vlakken uitgevoerd die true zijn in de loop.
Je kunt de vlakfuncties wijzigen met enkele code-aanpassingen. De hoofdstructuur moet zo blijven als beschreven. Je kunt het deel binnen de if-voorwaarden van elk vlak veranderen.
if (face2 == true) { // TEMPERATUUR vlak
//START HIER WIJZIGEN
digitalWrite (LEDOFF, LOW); // als dit vlak true is, is de OFF-vlak led LOW
if (central.connected() == true) { // als de kubus BLE verbonden is
// lees temperatuurwaarde
int val = analogRead(pinTemp); // analoge waarde lezen
resistance=(float)(1023-val)*10000/val; // weerstand berekenen
temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // temperatuur berekenen
// activeringsvoorwaarden
if (temperature > tooHot) { // airconditioning activeren
digitalWrite(LEDhot, LOW); // verwarmingsled uit
digitalWrite(LEDcold, HIGH); // airco-led aan
termoChar.setValue(1); // via BLE conditie 1 = koud aan - warm uit
}
if (temperature < tooCold) { // verwarming activeren
digitalWrite(LEDhot, HIGH);
digitalWrite(LEDcold, LOW);
termoChar.setValue(2); // 2 = koud uit - warm aan
}
if (temperature > tooCold && temperature < tooHot) { // ideale temperatuur: niets activeren
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // 0 = koud uit - warm uit
}
}
//EIND HIER
}
Je moet het "true"-deel coderen (zoals in de vorige code) en ook het "false"-deel wanneer de kubus geschud wordt:
// TEMPERATUUR deactivering
if (lastFUNCTION == 2) { // TEMPERATUUR vlak
//START HIER WIJZIGEN
// als een centrale verbonden is met de periferie:
if (central.connected() == true) {
digitalWrite(LEDhot, LOW); // temperatuur rode led uit
digitalWrite(LEDcold, LOW); // temperatuur blauwe led uit
termoChar.setValue(0); // temperatuur BLE signaal: 0 = koud uit - warm uit
//EIND HIER
}
Serial.println("TEMPERATUUR false - SLUIT");
face2 = false; // TEMPERATUUR vlak wordt false
}
Onthoud om het vlak op false te zetten wanneer je het schudt.
App:
Om de BLE-uitgangen van de kubus te zien kun je deze app downloaden: nRF Connect
https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=it
Wanneer je het opent, zoek naar apparaten en verbinding maken met "smartcubesketch". Dan zie je drie "Automation IO"-tabbladen, klik erop en druk de continue data collector.
Het is belangrijk om de kubus te verbinden omdat sommige functies (lichten, temperatuur en tv) alleen uitgevoerd worden als de kubus verbonden is.
Hoe het werkt: VIDEO
Upload de code, steek de batterij erin, sluit de doos en...
...nu heb je een SMART CUBE!
Ik heb een video gemaakt om je alle functies van de kubus en hoe je het gebruikt te tonen.
Conclusies
Dit project is alleen de eerste stap naar een slim huis. Mijn doel was om het potentieel van het Arduino 101-board te benutten om iets nieuws te creëren. Ik denk dat de accelerometer en gyroscoop het board nieuwe mogelijkheden geven in termen van mobiliteit. Met BLE is het naast draagbaar ook makkelijk te verbinden.
Dit is de eerste keer dat ik concreet een van mijn projecten realiseer (ik bedoel met een werkend prototype). Het was moeilijk en er waren enkele problemen onderweg, maar aan het eind heb ik veel geleerd en ben ik tevreden met het resultaat. Ik hoop dat iedereen die deze handleiding leest er iets van kan leren en dit project op hun behoeften aanpast. Excuses voor mijn slechte Engels, maar ik hoop dat de afbeeldingen je kunnen helpen.
In de toekomst van dit project verwacht ik de centrale te creëren die de brug is tussen de smart cube en de actuatoren (lichten, temperatuur, tv...). Deze centrale ontvangt het BLE-signaal van de kubus en gebruikt deze informatie om slimme dingen in je huis te doen.
Ik ben heel blij dat ik de kans had om Arduino 101 en de Grove kit te gebruiken (de kit is heel eenvoudig en snel voor prototyping).
Ik hoop dat het gebruik van het board op deze manier een inspiratie kan zijn voor je project. Je kunt het personaliseren zoals je wilt: Ik ben benieuwd welke functies jij gaat creëren en in welke andere contexten je het gaat gebruiken!
Misschien is dit geen revolutie, maar het is een nieuwe manier om met je huis te interacteren.
Ik hoop dat je deze tutorial leuk vindt.
Nu is het jouw beurt: leg je handen op de kubus en hack het!
Code
SMART CUBE - complete code met commentaar Arduino
// Bibliotheken
#include "CurieIMU.h" // Accelerometer & Gyroscoop
#include <CurieBLE.h> // Bluetooth Low Energy
#include <Wire.h>
#include "rgb_lcd.h" // LCD
#include <Keypad.h> // Keypad
rgb_lcd lcd; // LCD initialisatie
// Bluetooth initialisatie:
BLEPeripheral blePeripheral; // BLE Peripheral Device (het board dat je programmeert)
// BLE Services
BLEService lightsService("1815"); // BLE Automation IO (1815) - lichten informatie
BLEService termoService("1815"); // BLE Automation IO - temperatuur informatie
BLEService TVService("1815"); // BLE Automation IO - tv informatie
// BLE characteristics
BLEUnsignedCharCharacteristic lightsChar("2A56", // BLE characteristic Digital (2A56) - lichten
BLERead | BLENotify);
BLEUnsignedCharCharacteristic termoChar("2A56", // BLE characteristic Digital - temperatuur
BLERead | BLENotify);
BLEUnsignedCharCharacteristic TVChar("2A58", // BLE characteristic Analog (2A58) - tv
BLERead | BLENotify);
// Constanten en variabelen declaratie:
// Vlakte oriëntatie en schudfuncties:
int lastOrientation = -1; // vorige oriëntatie (voor vergelijking)
unsigned long previousMillis = 0; // laatste tijdupdate
unsigned long interval = 2000; // wachttijd in bovenpositie voor vlakactivering
unsigned long SHAKEpreviousMillis = 0; // laatste tijdupdate
unsigned long SHAKEinterval = 2000; // wachttijd tijdens schudden voor vlakdeactivering
boolean keep = false; // wordt gebruikt om maar één keer de vlakoriëntatieverandering te tellen
int lastFUNCTION = -1; // wordt gebruikt om de vorige oriëntatie te weten
// Vlakte initialisatie: aan het begin is elk vlak false
boolean face0 = false;
boolean face1 = false;
boolean face2 = false;
boolean face3 = false;
boolean face4 = false;
boolean face5 = false;
// LICHTEN vlak
const int LEDlights = 11; // pin 11: gele led
// TEMPERATUUR vlak
const int pinTemp = A0; // pin A0: temperatuursensor
const int LEDhot = 12; // pin 12: rode led
const int LEDcold = 13; // pin 13: blauwe led
float temperature; // temperatuurwaarde opslag
int B=3975; // B-waarde van de thermistor
float resistance; // weerstandswaarde opslag
float tooHot = 26.0; // temperatuur waarop airconditioning activeert [INSTELLEN]
float tooCold = 23.0; // temperatuur waarop verwarming activeert [INSTELLEN]
// TIMER vlak
int BUZZER = 3; // pin 3: buzzer
boolean KEEPtime = false; // wordt gebruikt om maar één keer de vlakoriëntatieverandering te tellen (niet opnieuw starten tijdens tellen)
int TIMERmillis = 0; // het volgende is voor de aftellingbepaling
int prevSHOWsecond = 0;
int CountdownInMillis = 0;
int SHOWmillis = 0; // millis-waarde berekeningsresultaat
int SHOWminute = 0; // minutenwaarde om te tonen in de monitor voor de aftelling
int SHOWseconds = 0; // secondenwaarde om te tonen in de monitor voor de aftelling
const int SETminute = 2; // stel 2 minuten timer in [INSTELLEN]
const int SETsecond = 30; // stel 30 seconden timer in [INSTELLEN]
// GELUID vlak
const int soundLED = 9; // pin 9: groene led
const int soundSENSOR = A1; // pin A0: geluidssensor
int brightness = 0; // groene led helderheid initialisatie
// TV vlak
const byte ROWS = 4; // vier rijen keypad
const byte COLS = 3; // drie kolommen keypad
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
}; // keypad knopwaarden
byte rowPins[ROWS] = {10,8,7,6}; // pin 10,8,7,6: verbinden met de rij-pinouts van het keypad
byte colPins[COLS] = {5,4,2}; // pin 5,4,2: verbinden met de kolom-pinouts van het keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // keypad initialisatie
// UIT vlak
const int LEDOFF = A2; // pin A2: rode led
void setup() {
pinMode(LEDlights, OUTPUT); // elke led instellen als output
pinMode(LEDhot, OUTPUT);
pinMode(LEDcold, OUTPUT);
pinMode(soundLED, OUTPUT);
pinMode(LEDOFF, OUTPUT);
Serial.begin(9600); // Serieel communicatie initialiseren
CountdownInMillis = (SETminute*60 + SETsecond)*1000; // berekent de corresponderende waarde in millis van minuten en seconden instelling
lcd.begin(16, 2); // LCD initialisatie
lcd.setRGB(0, 0, 0); // LCD RGB is UIT aan het begin
// apparaat initialiseren
Serial.println("IMU-apparaat initialiseren...");
CurieIMU.begin(); // IMU starten
// Stel accelerometerbereik in op 2G
CurieIMU.setAccelerometerRange(2);
// Schokdetectie inschakelen
CurieIMU.setDetectionThreshold(CURIE_IMU_SHOCK, 7000); // 7.0g = 7000 mg (deze waarde stelt de intensiteit van de schok in)
CurieIMU.setDetectionDuration(CURIE_IMU_SHOCK, 2000); // 2000ms (deze waarde stelt de duur van de schok in)
CurieIMU.interrupts(CURIE_IMU_SHOCK);
// BLE setup initialisatie
blePeripheral.setLocalName("SmartCubeSketch"); // de naam van het project
blePeripheral.setAdvertisedServiceUuid(lightsService.uuid()); // voeg de lichten service UUID toe
blePeripheral.addAttribute(lightsService); // voeg de BLE lichten service toe
blePeripheral.addAttribute(lightsChar); // voeg de BLE lichten characteristic toe
lightsChar.setValue(3); // initiële waarde voor deze characteristic = 3
// BLE lichten waarde betekenis: 0 = lichten uit, 1 = lichten aan, 3 = initiële staat, 4 = niet gebruikt
blePeripheral.setAdvertisedServiceUuid(termoService.uuid()); // voeg de temperatuur service UUID toe
blePeripheral.addAttribute(termoService); // voeg de BLE temperatuur service toe
blePeripheral.addAttribute(termoChar); // voeg de BLE temperatuur characteristic toe
termoChar.setValue(0); // initiële waarde is 0: koud uit - warm uit
// BLE termo waarde betekenis: 0 = koud uit - warm uit, 1 = koud aan - warm uit, 2 = koud uit - warm aan, 3 = niet gebruikt
blePeripheral.setAdvertisedServiceUuid(TVService.uuid()); // voeg de tv service UUID toe
blePeripheral.addAttribute(TVService); // voeg de BLE tv service toe
blePeripheral.addAttribute(TVChar); // voeg de tv characteristic toe
TVChar.setValue('x'); // initiële waarde voor deze characteristic (x betekent niets)
// BLE TV waarde betekenis: #nummer correspondeert met ingedrukte knop, C: sluit TV, O: open TV, x: initiële staat
blePeripheral.begin();
Serial.println("Bluetooth-apparaat actief, wachten op verbindingen...");
}
// setup einde
void loop() {
BLECentral central = blePeripheral.central(); // BLE verbinding
unsigned long currentMillis = millis(); // huidige tijdwaarde in milliseconden
// de volgende code komt van www.arduino.cc/en/Tutorial/Genuino101CurieIMUccelerometerOrientation
// wordt gebruikt om de oriëntatie van het board te detecteren
int orientation = -1; // de oriëntatie van het board
String orientationString; // string voor beschrijving van oriëntatie
// lees accelerometer:
int x = CurieIMU.readAccelerometer(X_AXIS);
int y = CurieIMU.readAccelerometer(Y_AXIS);
int z = CurieIMU.readAccelerometer(Z_AXIS);
// bereken absolute waarden om de grootste te bepalen
int absX = abs(x);
int absY = abs(y);
int absZ = abs(z);
if ((absZ > absX) && (absZ > absY)) {
// basis oriëntatie op Z
if (z > 0) {
orientationString = "up";
orientation = 0;
} else {
orientationString = "down";
orientation = 1;
}
} else if ((absY > absX) && (absY > absZ)) {
// basis oriëntatie op Y
if (y > 0) {
orientationString = "digitale pennen up";
orientation = 2;
} else {
orientationString = "analoge pennen up";
orientation = 3;
}
} else {
// basis oriëntatie op X
if (x < 0) {
orientationString = "connector up";
orientation = 4;
} else {
orientationString = "connector down";
orientation = 5;
}
}
// einde van de tutorialcode.
// op dit punt heb je de oriëntatiewaarde van het board constant bijgewerkt:
/* De oriëntaties van het board:
0: plat, processor naar boven (TIMER)
1: plat, processor naar beneden (TV)
2: landschap, analoge pennen naar beneden (TEMPERATUUR)
3: landschap, analoge pennen naar boven (UIT)
4: portret, USB-connector naar boven (LICHTEN)
5: portret, USB-connector naar beneden (GELUID)
*/
// voor dit project moet je weten of het vlak is veranderd ten opzichte van het vorige vlak [lastFUNCTION != orientation]
// maar deze informatie wordt alleen geprint als het vlak in de BOVEN-positie is gedurende meer dan [interval] tijd
// en alleen voor één keer [keep] (je hoeft het vlak niet constant te activeren, je hebt het maar één keer nodig)
// omdat de oriëntatiewaarde constant bijgewerkt wordt, moet je beginnen met tellen wanneer de oriëntatie verandert [orientation != lastOrientation]
if (orientation != lastOrientation) {
// als de oriëntatie is veranderd, begin met tellen
lastOrientation = orientation; // onthoud de huidige oriëntatie van het vlak
previousMillis = currentMillis; // onthoud de tijd wanneer het vlak is veranderd
keep = false;
} else if (currentMillis - previousMillis > interval && keep == false && lastFUNCTION != orientation) {
// deze voorwaarde print de oriëntatie alleen als het vlak voor een interval omhoog is
// en alleen voor één keer (keep)
// en alleen als het vlak anders is dan de vorige lus
Serial.println(orientationString); // print de oriëntatie
// het huidige vlak [orientation] wordt op true gezet (dat betekent dat de vlakfunctie geactiveerd is)
if (orientation == 1) { // TV vlak
face1 = true; // TV vlak wordt true
lastFUNCTION = orientation; // onthoud deze activering in [lastFUNCTION]
Serial.println("TV true"); // print het geactiveerde vlak
TVChar.setValue('O'); // O: open tv signaal (BLE): tv is open maar één keer
}
if (orientation == 4) { // LICHTEN vlak
face4 = true;
lastFUNCTION = orientation;
Serial.println("LICHTEN true");
}
if (orientation == 3) { // UIT vlak
face3 = true;
lastFUNCTION = orientation;
Serial.println("UIT true");
}
if (orientation == 5) { // GELUID vlak
face5 = true;
lastFUNCTION = orientation;
Serial.println("GELUID true");
}
if (orientation == 2) { // TEMPERATUUR vlak
face2 = true;
lastFUNCTION = orientation;
Serial.println("TEMPERATUUR true");
}
if (orientation == 0) { // TIMER vlak
face0 = true;
lastFUNCTION = orientation;
Serial.println("TIMER true");
if (KEEPtime == false) { // timer wordt alleen geactiveerd als het de 1e cyclus is of gestopt is
TIMERmillis = currentMillis; // begin met tellen
}
}
keep = true; // [keep] verandert waarde zodat je in de volgende lus niet in deze voorwaarde kunt komen als het vlak niet verandert (voorkomt dat hetzelfde vlak nogmaals geactiveerd wordt)
}
// deze voorwaarde is voor de schudfunctie: als je schudt gedurende meer dan [SHAKEinterval] tijd, wordt het vlak gedeactiveerd
if (CurieIMU.getInterruptStatus(CURIE_IMU_SHOCK) && currentMillis - SHAKEpreviousMillis > SHAKEinterval) {
Serial.println("SCHUDDEN"); // print "SCHUDDEN" als schudden gedetecteerd wordt
// het laatst geactiveerde vlak [lastFUNCTION] wordt op false gezet (dat betekent dat de vlakfunctie gedeactiveerd wordt)
// TV deactivering
if (lastFUNCTION == 1) { // TV vlak
TVChar.setValue('C'); // C: sluit de tv BLE signaal
Serial.println("TV false - SLUIT");
face1 = false; // TV vlak wordt false
}
// LICHTEN deactivering
if (lastFUNCTION == 4) { // LICHTEN vlak
if (central.connected() == true) { // als een centrale verbonden is met de periferie:
lightsChar.setValue(0); // LICHTEN UIT BLE signaal
digitalWrite(LEDlights, HIGH); // geele led aan om kubus in donker te vinden
}
Serial.println("LICHTEN false - SLUIT");
face4 = false; // LICHTEN vlak wordt false
}
// UIT
if (lastFUNCTION == 3) { // UIT vlak
// UIT vlak geschud: alles sluiten en rode led UIT openen
digitalWrite(LEDOFF, HIGH); // rode led UIT is aan wanneer kubus gesloten is
// nu alle geactiveerde functies sluiten:
// SLUIT TV
TVChar.setValue('C'); // C: sluit de tv BLE signaal
Serial.println("TV false - SLUIT");
face1 = false;
// SLUIT LICHTEN
Serial.println("LICHTEN false - SLUIT");
if (central.connected() == true) {
lightsChar.setValue(0);
digitalWrite(LEDlights, LOW); // lichten led is dicht als UIT vlak geschud wordt
}
face4 = false;
// SLUIT GELUID
analogWrite(soundLED, LOW); // geluid led sluiten
Serial.println("GELUID false - SLUIT");
face5 = false;
// SLUIT TEMPERATUUR
if (central.connected() == true) {
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // temperatuur BLE signaal: 0 = koud uit - warm uit
}
Serial.println("TEMPERATUUR false - SLUIT");
face2 = false;
// SLUIT TIMER
Serial.println("TIMER false - SLUIT");
lcd.setRGB(0, 0, 0); // de LCD RGB is dicht
lcd.clear();
KEEPtime = false;
face0 = false;
// De kubus is inactief, alleen UIT led is actief
Serial.println("UIT false - SLUIT");
face3 = false; // UIT vlak wordt false
}
// GELUID deactivering
if (lastFUNCTION == 5) { // GELUID vlak
analogWrite(soundLED, LOW); // geluid led sluiten
Serial.println("GELUID false - SLUIT");
face5 = false; // GELUID vlak wordt false
}
// TEMPERATUUR deactivering
if (lastFUNCTION == 2) { // TEMPERATUUR vlak
// als een centrale verbonden is met de periferie:
if (central.connected() == true) {
digitalWrite(LEDhot, LOW); // temperatuur rode led sluiten
digitalWrite(LEDcold, LOW); // temperatuur blauwe led sluiten
termoChar.setValue(0); // temperatuur BLE signaal: 0 = koud uit - warm uit
}
Serial.println("TEMPERATUUR false - SLUIT");
face2 = false; // TEMPERATUUR vlak wordt false
}
// TIMER deactivering
if (lastFUNCTION == 0) { // TIMER vlak
Serial.println("TIMER false - SLUIT");
face0 = false; // TIMER vlak wordt false
// als je de kubus schudt tijdens de aftelling, wordt de LCD rood en toont de resterende tijd
lcd.setRGB(180, 40, 0); // de RGB-backlight wordt rood
lcd.clear(); // lcd wordt gewist
lcd.setCursor(0, 0);
lcd.print("STOP OP ");
lcd.setCursor(8, 0);
lcd.print(SHOWminute); // geeft de minuten aan wanneer je de kubus schudt
lcd.setCursor(9, 0);
lcd.print(":");
lcd.setCursor(10, 0);
lcd.print(SHOWseconds); // geeft de seconden aan wanneer je de kubus schudt
tone(BUZZER,1000,1000); // het maakt een kort geluid
delay(2000);
lcd.clear(); // LCD wissen
lcd.setRGB(0, 0, 0); // LCD RGB-backlight is dicht
KEEPtime = false; // TIMER vlak wordt false
}
SHAKEpreviousMillis = currentMillis; // onthoud de waarde voor de [SHAKEinterval] berekening
}
// de volgende instructies worden in de lus uitgevoerd alleen als het vlak geactiveerd is
if (face1 == true) { // TV vlak
digitalWrite(LEDOFF, LOW); // als dit vlak true is, is de UIT-vlak led LOW
if (central.connected() == true) { // als de kubus BLE verbonden is
char key = keypad.getKey(); // lees de waarde van het keypad
if (key && orientation == 1){ // als er iets ingedrukt is en alleen wanneer het tv-vlak boven is (voorkomt ongewilde keypad-aanrakingen)
if (key == '0') { // als de ingedrukte toets 0 is
TVChar.setValue(key); // stuur de [key] waarde via BLE
Serial.println(key); // print de ingedrukte knop (commentaar als je deze info niet wilt tonen)
}
if (key == '1'){ TVChar.setValue(key); Serial.println(key); }
if (key == '2'){ TVChar.setValue(key); Serial.println(key); }
if (key == '3'){ TVChar.setValue(key); Serial.println(key); }
if (key == '4'){ TVChar.setValue(key); Serial.println(key); }
if (key == '5'){ TVChar.setValue(key); Serial.println(key); }
if (key == '6'){ TVChar.setValue(key); Serial.println(key); }
if (key == '7'){ TVChar.setValue(key); Serial.println(key); }
if (key == '8'){ TVChar.setValue(key); Serial.println(key); }
if (key == '9'){ TVChar.setValue(key); Serial.println(key); }
if (key == '*'){ TVChar.setValue(key); Serial.println(key); }
if (key == '#'){ TVChar.setValue(key); Serial.println(key); }
}
}
}
if (face4 == true) { // LICHTEN vlak
digitalWrite(LEDOFF, LOW); // als dit vlak true is, is de UIT-vlak led LOW
if (central.connected() == true) { // als een centrale verbonden is met de periferie:
lightsChar.setValue(1); // LICHTEN geactiveerd BLE signaal
digitalWrite(LEDlights, LOW); // gele led is dicht omdat huislichten aan zijn
}
}
if (face3 == true) { // UIT vlak
// wanneer UIT vlak boven is, wordt niets gedaan
digitalWrite(LEDOFF, LOW); // led UIT wordt alleen geactiveerd wanneer de kubus geschud wordt, dus nu LOW
}
if (face5 == true) { // GELUID vlak
digitalWrite(LEDOFF, LOW); // als dit vlak true is, is de UIT-vlak led LOW
// geluidssensor geactiveerd, led helderheid geregeld door het geluid
// deze code komt van helderheidsregeling voorbeeld
long sum = 0;
for (int i=0; i<32; i++) {
sum += analogRead(soundSENSOR);
}
sum >>= 5;
brightness = (sum*255)/1024; // helderheidswaarde berekenen
analogWrite(soundLED, brightness); // groene led helderheid wordt geregeld door het geluid
delay(50);
}
if (face2 == true) { // TEMPERATUUR vlak
digitalWrite(LEDOFF, LOW); // als dit vlak true is, is de UIT-vlak led LOW
if (central.connected() == true) { // als de kubus BLE verbonden is
// lees temperatuurwaarde
int val = analogRead(pinTemp); // analoge waarde lezen
resistance=(float)(1023-val)*10000/val; // weerstand berekenen
temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // temperatuur berekenen
// activeringsvoorwaarden
if (temperature > tooHot) { // airconditioning activeren
digitalWrite(LEDhot, LOW); // verwarmingsled sluiten
digitalWrite(LEDcold, HIGH); // airco-led openen
termoChar.setValue(1); // stel via BLE de conditie 1 = koud aan - warm uit
}
if (temperature < tooCold){ // verwarming activeren
digitalWrite(LEDhot, HIGH);
digitalWrite(LEDcold, LOW);
termoChar.setValue(2); // 2 = koud uit - warm aan
}
if (temperature > tooCold && temperature < tooHot){ // ideale temperatuur: niets activeren
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // 0 = koud uit - warm uit
}
}
}
if (face0 == true) { // TIMER vlak geactiveerd
digitalWrite(LEDOFF, LOW); // als dit vlak true is, is de UIT-vlak led LOW
// dit berekent de tijd om in het display te tonen
SHOWmillis = (CountdownInMillis - (currentMillis - TIMERmillis))/1000;
SHOWminute = SHOWmillis/60; // minutenwaarde om in de LCD te tonen
SHOWseconds = SHOWmillis%60; // secondenwaarde om in de LCD te tonen
lcd.setRGB(50, 100, 70); // open LCD met RGB blauwe kleur
if (prevSHOWsecond != SHOWseconds){ // vernieuw het scherm elke seconde (omdat vernieuwen elke lus te snel is)
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("TIMER ");
lcd.setCursor(7, 0);
lcd.print(SETminute); // schrijft de minuten die je ingesteld hebt
lcd.setCursor(8, 0);
lcd.print(":");
lcd.setCursor(9, 0);
lcd.print(SETsecond); // schrijft de seconden die je ingesteld hebt
lcd.setCursor(0, 1);
lcd.print(SHOWminute); // schrijft de huidige resterende minuten
lcd.setCursor(1, 1);
lcd.print(":");
lcd.setCursor(2, 1);
lcd.print(SHOWseconds); // schrijft de huidige resterende seconden
KEEPtime = true;
prevSHOWsecond = SHOWseconds; // om elke seconde te vernieuwen
}
if (SHOWminute == 0 && SHOWseconds == 0) { // wanneer aftelling eindigt
lcd.clear(); // LCD wissen
lcd.setCursor(4, 0);
lcd.setRGB(180, 40, 0); // LCD RGB wordt rood
lcd.print("TIJD OP");
tone(BUZZER,1000,500); // drie geluiden
delay(900);
tone(BUZZER,1000,500);
delay(900);
tone(BUZZER,1000,1000);
delay(1500);
lcd.clear(); // wissen en sluiten van de LCD
lcd.setRGB(0, 0, 0);
face0 = false; // TIMER vlak is nu gesloten (false)
KEEPtime = false;
}
}
} // loop einde
Aangepaste onderdelen en behuizingen
Dit is het bestand (.dxf) dat je op je lasersnijder kunt uploaden. Ik gebruikte een medium density fiberboard (MDF) van 3mm. Snij de zwarte lijnen en graveer de rode lijnen. Belangrijk: als je materiaaldikte anders is, moet je deze schets aanpassen.
smart_cube_8sVCflFmhM.dxf
Hetzelfde bestand van de doos maar in een ander formaat: .pdf
Schema's
Dit is een .jpeg van het Fritzing-schema (gele draden zijn verbonden met Grove-componenten)

Dit is een schema van de verbindingen in de Grove Shield
_cI0IwUsPVZ.Base%20shield%20connections
Productieproces
- Waarom Een Iets Groter Ontwerp Innovatie Kan Versnellen En Risico Verminderen
- Een Betaalbaar Draadloos Sensornetwerk Bouwen voor Uw Huis
- Je huis temperatuur monitoren met een Raspberry Pi-dashboard
- Slimme Plant IoT: Verbonden kassen bouwen met Arduino & Azure
- Je plafondventilator bedienen met Alexa: Stap-voor-stap handleiding
- Zonnepanelen: Een Wijze Investering voor Uw Huis
- Hoe slimme huistechnologie het alledaagse leven transformeert
- De smart home skills gap overbruggen: Waarom Groot-Brittannië achterloopt op Europa
- Slimme Huis Evolutie: Wat de Toekomst Inhoudt voor Verbonden Leven
- Slimme beveiliging: Expertstrategieën om uw thuis-IoT-apparaten te beschermen tegen hackers
- Hoe U De Beveiliging Van Uw Slimme Huis Versterkt: Expert Tips