Virtual 3D Device Port – SU15-22-Accelerometer (ADXL345)
In het vorige hoofdstuk heb je gezien hoe we een virtuele potmeter kunnen maken in google sketchup als je de basis onder de knie hebt, we gaan nu een stapje verder door een accelerometer (ADXL345) te koppelen met SketchUp waarbij 2 gegevens nodig zijn, te weten de X en Y coördinaten, ik heb er een “doolhof” spel van gemaakt.
Sluit de accelerometer aan volgens onderstaand schema:
De Arduino programmeren
Het voorbeeld script genereert deze gegevens in STABIELE horizontale ligging:
En als je de module beweegt:
Wat moeten we doen?
1) We hebben in dit geval niets aan de Z coördinaat, dus die coderegels kunnen we eruit halen.
2) In stabiele horizontale ligging, staan de getallen niet op 0, hier moeten we dus een autocorrectie op doen, dit doen we door de allereerste coördinaten op te slaan en later van de gemeten waarde af te trekken.
1 2 3 4 5 |
if (a < 1) { xc = (((int)_buff[1]) << 8) | _buff[0]; yc = (((int)_buff[3]) << 8) | _buff[2]; a = 1; } else { |
3) We hebben getallen nodig van 0.00 tot 1.00, deze kunnen we MAPPEN via de Arduino code, de waarde om te MAPPEN kun je zelf uitlezen door de module 90 graden te kantelen aan de 4 zijden.
1 2 |
float xval = map(x - xc, -160, 160, 0, 1000); float yval = map(y - yc, -150, 150, 0, 1000); |
Ik heb het script omgebouwd tot deze variant, waar nodig de code aan je eigen situatie aanpassen!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#include <Wire.h> #define DEVICE (0x53) // Device address as specified in data sheet byte _buff[6]; char POWER_CTL = 0x2D; //Power Control Register char DATA_FORMAT = 0x31; char DATAX0 = 0x32; //X-Axis Data 0 char DATAX1 = 0x33; //X-Axis Data 1 char DATAY0 = 0x34; //Y-Axis Data 0 char DATAY1 = 0x35; //Y-Axis Data 1 char DATAZ0 = 0x36; //Z-Axis Data 0 char DATAZ1 = 0x37; //Z-Axis Data 1 int xc, yc; int a=0; void setup() { Wire.begin(); // join i2c bus (address optional for master) Serial.begin(9600); // start serial for output. Make sure you set your Serial Monitor to the same! //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register. writeTo(DATA_FORMAT, 0x01); //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register. writeTo(POWER_CTL, 0x08); } void loop() { uint8_t howManyBytesToRead = 6; readFrom( DATAX0, howManyBytesToRead, _buff); //read the acceleration data from the ADXL345 // each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!! // thus we are converting both bytes in to one int // Deze IF loop slaat de allereerste gemeten waarde van de coordinaten op, // om zo een correctie uit te voeren en in horizontale stand op 0 te beginnen. if (a < 1) { xc = (((int)_buff[1]) << 8) | _buff[0]; yc = (((int)_buff[3]) << 8) | _buff[2]; a = 1; } else { int x = (((int)_buff[1]) << 8) | _buff[0]; int y = (((int)_buff[3]) << 8) | _buff[2]; // MAP de getallen van X en Y MAX en MIN van 0 t/m 1000. float xval = map(x - xc, -160, 160, 0, 1000); float yval = map(y - yc, -150, 150, 0, 1000); // Deze correctie is nodig omdat de gegevens soms net // iets buiten het bereik kunnen komen. if (xval > 1000) {xval = 1000;} if (xval < 0) {xval = 0;} if (yval > 1000) {yval = 1000;} if (yval < 0) {yval = 0;} // Print de gegevens X en Y met als scheidingsteken een komma. // Ps. vergeet niet af te sluiten met een nieuwe lijn. Serial.print(xval / 1000); Serial.print(","); Serial.println(yval / 1000); // Lees de module uit elke 0,05 seconden. delay(50); } } void writeTo(byte address, byte val) { Wire.beginTransmission(DEVICE); // start transmission to device Wire.write(address); // send register address Wire.write(val); // send value to write Wire.endTransmission(); // end transmission } // Reads num bytes starting from address register on device in to _buff array void readFrom(byte address, int num, byte _buff[]) { Wire.beginTransmission(DEVICE); // start transmission to device Wire.write(address); // sends address to read from Wire.endTransmission(); // end transmission Wire.beginTransmission(DEVICE); // start transmission to device Wire.requestFrom(DEVICE, num); // request 6 bytes from device int i = 0; while(Wire.available()) {// device may send less than requested (abnormal) _buff[i] = Wire.read(); // receive a byte i++; } Wire.endTransmission(); // end transmission } |
Als we nu bovenstaande code opslaan in de Arduino en je opent de seriële monitor, dan zijn dit de gegevens bij stabiele horizontale ligging:
En als je de module beweegt:
Actie in SketchUp
Nu de Arduino haar data verzend via de seriële poort naar de computer toe, kunnen wij deze met een script voor SketchUp weer uitlezen, ik heb voor het testen een doolhofje gemaakt (onderaan te downloaden)
Voor het splijten van de seriële data (de waarden van X en Y), heb ik deze ruby code toegepast:
x, y = serialdata.split(",")
In het model vink je aan “scripted” en daar moet deze code worden geplaatst, er zijn commentaarregels toegevoegd:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# DomoticX Virtual 3D Device Port SU15 interface. # Wat moet er gebeuren bij het starten van de simulatie? onstart{ compoortopties = ["Seriele poort:", "Baudrate:"] # Standaard waarden!, deze kun je zelf aanpassen! standaard = ["COM8", "9600"] # Lijst met baudrates voor de dropdownlijst in het menu. baudratelijst = ["", "4800|9600|14400|19200|28800|38400|57600|115200"] # Geef het dialoogvenster weer voor vraag naar gegevens. serialsettings = UI.inputbox(compoortopties, standaard, baudratelijst, "Seriele poort instellingen:") if serialsettings != FALSE # Haal de instellingen uit het diagloogvenster en koppel deze aan een variabele. $comport = serialsettings[0] $baudrate = serialsettings[1].to_i begin # Open de seriele poort. @serial = Serial.new($comport, $baudrate) rescue RubySerial::Exception => e # Sluit de seriele poort als deze open staat. @serial.close if @serial # Reset/stop de simulatie. MSketchyPhysics3::SketchyPhysicsClient.physicsReset # Geef een bericht dat de seriele poort niet is gevonden. UI.messagebox("Seriele poort niet gevonden!") end else # Reset/stop de simulatie. MSketchyPhysics3::SketchyPhysicsClient.physicsReset end } # Wat moet er gebeuren tijdens de simulatie? ontick{ # Sluit het 'control panel' venster bij het starten van de simulatie. MSketchyPhysics3.closeControlPanel if frame == 1 # Lees de data van de seriele poort in. $serialdata = @serial.read(1024) # Splits de binnengekomen data in 2 variabelen. x, y = $serialdata.split(",") # Zet de waarden om in variabelen (strings). $x = x.to_f $y = y.to_f # Geef de gegevens weer aan de linker zijde (log). logLine("COM poort: " + $comport.to_s) logLine("BAUD rate: " + $baudrate.to_s) logLine("Seriele data: " + $serialdata.to_s) logLine("") logLine("Doolhof X: " + $x.to_s) logLine("Doolhof Y: " + $y.to_s) logLine("") logLine("") logLine("") } # Wat moet er gebeuren als de de simulatie stopt? onend{ # Sluit de seriele poort als deze open staat. @serial.close if @serial } |
De servo’s kunnen ingesteld worden met in de controllers de variabelen $x en $y:
De servo’s kunnen gekoppeld worden aan de “doolhof”:
Alles in actie
1) Sluit de Arduino aan met bovenstaand Arduino script geladen (pas eventueel de COM poort aan in het Python script).
2) Druk op de “play” knop om de simulatie te starten.
Nu zal het “doolhof” zich gaan bewegen, zoals je ook de accelerometer ADXL345 beweegt!
De gegevens X en Y worden aan de linkerkant weergegeven!
Hoe werkt het?
Dit werkt nu via een seriele verbinding tussen de Arduino en de computer, de arduino stuurt 2 getallen (FLOAT) voor de X en Y beweging tussen 0.00 en 1.00.
In Sketchup SketchyPhysics is:
– 0.00 de status van het object opgegeven bij de MIN waarde (bijvoorbeeld -135 graden)
– 1.00 de status van het object opgegeven bij de MAX waarde (bijvoorbeeld 135 graden)
Daaruit volgt dat tussen 0.00 en 1.00, 270 graden zit, omdat sketchup met stapjes van 0.01 werkt zijn er 100 stapjes dus 2,7 graden per stapje.
- SketchyPhysics - SU15-33-LED aan-uit schakelen (sketchup).skp.7z 225,84 kb
- SketchyPhysics - SU15-33-LED aan-uit schakelen (ruby script).rb.7z 1,09 kb
- SketchyPhysics - SU15-33-LED aan-uit schakelen (arduino script).ino.7z 0,69 kb
- SketchyPhysics - SU15-32-RGB LED aansturen (sketchup).skp.7z 61,30 kb
- SketchyPhysics - SU15-32-RGB LED aansturen (ruby-python scripts).ino.7z 1,76 kb
- SketchyPhysics - SU15-32-RGB LED aansturen (arduino script).ino.7z 0,80 kb
- SketchyPhysics - SU15-31-Servo aansturen (SG90) (arduino script).ino.7z 0,82 kb
- SketchyPhysics - SU15-30-Hendel status voorbeeld compleet naar Arduino (ruby script).rb.7z 1,70 kb
- Sketchyphysics - SU15-30-Hendel status naar Arduino (sketchup).skp.7z 31,52 kb
- SketchyPhysics - SU15-23-Gyroscoopmeter (GY-521) (arduino script).ino.7z 1,02 kb
- SketchyPhysics - SU15-22-Accelerometer (ADXL345) (sketchup).skp.7z 74,49 kb
- SketchyPhysics - SU15-22-Accelerometer (ADXL345) (ruby script).rb.7z 1,14 kb
- SketchyPhysics - SU15-22-Accelerometer (ADXL345) (arduino script).ino.7z 1,50 kb
- SketchyPhysics - SU15-21-Virtuele Potmeter (sketchup).skp.7z 51,62 kb
- SketchyPhysics - SU15-21-Virtuele Potmeter (ruby-python script).rb.7z 1,03 kb
- SketchyPhysics - SU15-21-Virtuele Potmeter (arduino script).ino.7z 0,60 kb
- SketchyPhysics - SU15-21-Potmeter orgineel model (sketchup).skp.7z 91,66 kb
- Sketchyphysics - SU15-20-Communicatie naar SU (sketchup).skp.7z 22,37 kb
- SketchyPhysics - SU15-20-Communicatie naar SU (ruby script).rb.7z 1,03 kb
- SketchyPhysics - SU15-20-Communicatie naar SU (arduino script).ino.7z 0,33 kb
- SketchyPhysics - SU15-12-Waarde uitlezen van object voorbeeld van forum (sketchup).7z 71,97 kb
- SketchyPhysics - SU15-10-Basis oefening (sketchup).skp.7z 19,25 kb
- SketchyPhysics - SU14&15 - Library FFI+RubySerial.7z 167,31 kb