Virtual 3D Device Port – SU08-30-Communicatie naar Arduino
Hieronder volgen een aantal stappen om seriële data via een seriële poort naar de arduino te zenden en deze om te zetten in een beweging in van bijvoorbeeld een servo.
Voor dit voorbeeld had ik hulp in moeten roepen op het forum van sketchucation, het blijkt namelijk helemaal NIET eenvoudig te zijn om de status 0.00 t/m 1.00 van een schanier of servo uit te lezen in SketchUp 8, er moeten diverse wiskundige berekeningen gemaakt worden om het aantal graden te onttrekken.
Het voorbeeld uit het forum is gemaakt in SU2013, de hoek in graden word getoond:
Dit is de Ruby code in het script gedeelte van de hendel:
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 |
onStart { @lever = this @lever_base = nil # Find lever base simulation.bodies.each { |body| next if body.group.name != 'lever_base' @lever_base = body break } # Store initial lever up direction relative to base. up = this.transformation.zaxis.transform(@lever_base.group.transformation.inverse).normalize @angle = 0 # Calculate initial angle @init_angle = Math.acos(up.x) @init_angle = -@init_angle if up.z < 0 # Create text, just to output info. @text = Sketchup.active_model.add_note("Lever angle", 0.01, 0.05) } onUpdate { # Get current lever up direction relative to base. up = this.transformation.zaxis.transform(@lever_base.group.transformation.inverse).normalize # Calculate current angle theta = Math.acos(up.x) theta = -theta if up.z < 0 # Get the difference angle @angle = theta - @init_angle @angle += Math::PI*2 if @angle < -Math::PI @angle -= Math::PI*2 if @angle > Math::PI # Display angle @text.text = "Lever angle: #{@angle.radians.round} degrees" } onEnd { # Remove text @text.erase! if @text.valid? } |
Omdat de hoek zowel positief als negatief kan zijn, is het handiger om met de MIN en MAX waarden te werken (naar de arduino toe), daarvoor heb ik dit stukje code gemaakt, je plaatst het in het “onUpdate” blok aan het eind:
1 2 3 4 |
anglefloat = @angle.radians.round.to_f puts (((0.5 / 90) * anglefloat) + 0.5).round(2) if anglefloat > 0 puts (((-0.5 / 90) * anglefloat) - 0.5).abs.round(2) if anglefloat < 0 puts 0.5 if anglefloat == 0 |
Als je nu de RUBY Console opent, kun je de waarde 0.00 t/m 1.00 zien als je de hendel verplaatst:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
0.54 0.53 0.53 0.53 0.52 0.51 0.5 0.49 0.49 0.48 0.48 0.47 0.46 0.46 0.45 0.44 0.43 0.43 0.42 0.41 0.41 0.4 0.39 |
Sketchup 8
Om te gebruiken in SU8 (en om python te gebruiken), moeten we het model eerst opslaan voor versie 8 van SU:
Nu kunnen we de hendel ook gebruiken voor SU8, maar er is echter een probleem, zodra je in SU8 aan de hendel zit, verschijnt deze foutmelding:
SketchUp 8 gebruikt een andere Ruby versie (1.x.x) en heeft bij de functie “round” geen argumenten nodig, ik heb het na wat research opgelost met het volgende stukje code dat gebruik maakt van SPRINTF:
1 2 3 4 |
anglefloat = @angle.radians.round.to_f puts sprintf "%.2f", (((0.5 / 90) * anglefloat) + 0.5) if anglefloat > 0 puts sprintf "%.2f", (((-0.5 / 90) * anglefloat) - 0.5).abs if anglefloat < 0 puts 0.5 if anglefloat == 0 |
Nu krijg je geen foutmelding en zie je in de RUBY console wederom de getallen tussen 0.00 en 1.00.
Getallen weergeven
Om het allemaal wat mooier te maken kun je “logLine” gebruiken, dit zijn “log” regels die verschijnen aan de linkerkant van het beeld, dat kan met dit stukje code:
1 2 3 4 5 6 7 8 9 10 11 12 |
anglefloat = @angle.radians.round.to_f angledata = sprintf "%.2f", (((0.5 / 90) * anglefloat) + 0.5) if anglefloat > 0 angledata = sprintf "%.2f", (((-0.5 / 90) * anglefloat) - 0.5).abs if anglefloat < 0 angledata = 0.5 if anglefloat == 0 logLine("Hendel status: " + angledata.to_s) logLine("Hendel hoek: " + @angle.radians.round.to_s) logLine("") logLine("") logLine("") logLine("") logLine("") logLine("") |
Daarnaast moet je wel de TEXT attributen weghalen, anders wordt het een wirwar op je scherm, de totale code in de “script” sectie ziet er dan zo uit:
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 |
onStart { @lever = this @lever_base = nil # Find lever base simulation.bodies.each { |body| next if body.group.name != 'lever_base' @lever_base = body break } # Store initial lever up direction relative to base. up = this.transformation.zaxis.transform(@lever_base.group.transformation.inverse).normalize @angle = 0 # Calculate initial angle @init_angle = Math.acos(up.x) @init_angle = -@init_angle if up.z < 0 # Create text, just to output info. } onUpdate { # Get current lever up direction relative to base. up = this.transformation.zaxis.transform(@lever_base.group.transformation.inverse).normalize # Calculate current angle theta = Math.acos(up.x) theta = -theta if up.z < 0 # Get the difference angle @angle = theta - @init_angle @angle += Math::PI*2 if @angle < -Math::PI @angle -= Math::PI*2 if @angle > Math::PI # Display angle #@text.text = "Lever angle: #{@angle.radians.round} degrees" anglefloat = @angle.radians.round.to_f angledata = sprintf "%.2f", (((0.5 / 90) * anglefloat) + 0.5) if anglefloat > 0 angledata = sprintf "%.2f", (((-0.5 / 90) * anglefloat) - 0.5).abs if anglefloat < 0 angledata = 0.5 if anglefloat == 0 # Geef gegevens aan de linkerkant weer. logLine("Hendel status: " + angledata.to_s) logLine("Hendel hoek: " + @angle.radians.round.to_s) logLine("") logLine("") logLine("") logLine("") logLine("") logLine("") } onEnd { } |
Gegevens naar seriële poort schrijven
Om nu de gegevens 0.00 t/m 1.00 naar de arduino te schrijven via de seriele poort, heb je de volgende Python code nodig in de volgende blokken onder “scripted”:
1 2 3 4 |
# Python commando om de seriele bibliotheek te importeren. Py.exec("import serial") # Python commando om de seriele poort te openen. Py.exec("ser = serial.Serial('COM8', 9600)") |
1 2 |
# Schrijf de data weg naar de seriele poort (incl. newline) Py.exec("ser.write(" + angledata.to_s + "\n)") |
1 2 |
# Sluit de seriele poort. Py.exec("ser.close()") |
De complete code
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 |
onStart { @lever = this @lever_base = nil # Find lever base simulation.bodies.each { |body| next if body.group.name != 'lever_base' @lever_base = body break } # Store initial lever up direction relative to base. up = this.transformation.zaxis.transform(@lever_base.group.transformation.inverse).normalize @angle = 0 # Calculate initial angle @init_angle = Math.acos(up.x) @init_angle = -@init_angle if up.z < 0 # Create text, just to output info. # Python commando om de seriele bibliotheek te importeren. Py.exec("import serial") # Python commando om de seriele poort te openen. Py.exec("ser = serial.Serial('COM8', 9600)") } onUpdate { # Get current lever up direction relative to base. up = this.transformation.zaxis.transform(@lever_base.group.transformation.inverse).normalize # Calculate current angle theta = Math.acos(up.x) theta = -theta if up.z < 0 # Get the difference angle @angle = theta - @init_angle @angle += Math::PI*2 if @angle < -Math::PI @angle -= Math::PI*2 if @angle > Math::PI # Display angle #@text.text = "Lever angle: #{@angle.radians.round} degrees" anglefloat = @angle.radians.round.to_f angledata = sprintf "%.2f", (((0.5 / 90) * anglefloat) + 0.5) if anglefloat > 0 angledata = sprintf "%.2f", (((-0.5 / 90) * anglefloat) - 0.5).abs if anglefloat < 0 angledata = 0.5 if anglefloat == 0 # Geef gegevens aan de linkerkant weer. logLine("Hendel status: " + angledata.to_s) logLine("Hendel hoek: " + @angle.radians.round.to_s) logLine("") logLine("") logLine("") logLine("") logLine("") logLine("") # Schrijf de data weg naar de seriele poort (incl. newline) Py.exec("ser.write(" + angledata.to_s + "\n)") } onEnd { # Sluit de seriele poort. Py.exec("ser.close()") } |
Hoe werkt het?
Dit werkt nu via een seriële verbinding tussen de computer en de Arduino , de computer stuurt getallen (FLOAT) tussen 0.00 en 1.00.
In Sketchup SketchyPhysics is:
– 0.00 de status van het object opgegeven bij de MIN waarde (bijvoorbeeld -90 graden)
– 1.00 de status van het object opgegeven bij de MAX waarde (bijvoorbeeld 90 graden)
Daaruit volgt dat tussen 0.00 en 1.00, 180 graden zit, omdat sketchup met stapjes van 0.01 werkt zijn er 100 stapjes dus 1,8 graden per stapje.
- SketchyPhysics - SU08-32-RGB LED aansturen (sketchup).7z 46,90 kb
- SketchyPhysics - SU08-32-RGB LED aansturen (ruby-python scripts).ino.7z 1,16 kb
- SketchyPhysics - SU08-32-RGB LED aansturen (arduino script).ino.7z 0,80 kb
- SketchyPhysics - SU08-31-Servo aansturen (SG90) (arduino script).ino.7z 0,82 kb
- SketchyPhysics - SU08-30-Hendel status voorbeeld compleet naar Arduino (sketchup 8).skp.7z 19,00 kb
- SketchyPhysics - SU08-30-Hendel status voorbeeld compleet naar Arduino (ruby-python script).rb.7z 0,93 kb
- SketchyPhysics - SU08-30-Hendel status voorbeeld compleet (sketchup 8).skp.7z 18,47 kb
- SketchyPhysics - SU08-30-Hendel status voorbeeld compleet (ruby-python script).rb.7z 0,75 kb
- SketchyPhysics - SU08-30-Hendel status voorbeeld (sketchup 2014).skp.7z 18,46 kb
- SketchyPhysics - SU08-30-Hendel orgineel voorbeeld omgezet (sketchup 8).skp.7z 17,68 kb
- SketchyPhysics - SU08-30-Hendel orgineel voorbeeld (sketchup 2013).skp.7z 24,89 kb
- SketchyPhysics - SU08-22-Accelerometer (ADXL345) (sketchup).skp.7z 53,98 kb
- SketchyPhysics - SU08-22-Accelerometer (ADXL345) (ruby-python script).rb.7z 0,67 kb
- SketchyPhysics - SU08-22-Accelerometer (ADXL345) (arduino script).ino.7z 1,52 kb
- SketchyPhysics - SU08-21-Virtuele Potmeter (sketchup).skp.7z 34,45 kb
- SketchyPhysics - SU08-21-Virtuele Potmeter (ruby-python script).rb.7z 0,56 kb
- SketchyPhysics - SU08-21-Virtuele Potmeter (arduino script).ino.7z 0,60 kb
- SketchyPhysics - SU08-21-Potmeter orgineel model (sketchup).skp.7z 91,66 kb
- SketchyPhysics - SU08-20-Communicatie naar SU (sketchup).skp.7z 14,91 kb
- SketchyPhysics - SU08-20-Communicatie naar SU (ruby-python script).rb.7z 0,59 kb
- SketchyPhysics - SU08-20-Communicatie naar SU (arduino script).ino.7z 0,33 kb
- SketchyPhysics - SU08-12-Waarde uitlezen van object voorbeeld van forum (sketchup).7z 61,51 kb
- SketchyPhysics - SU08-10-Basis oefening (sketchup).skp.7z 14,31 kb