Virtual 3D Device Port – SU15-30-Communicatie naar Arduino
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 scharnier of servo uit te lezen in SketchUp 2015, er moeten diverse wiskundige berekeningen gemaakt worden om het aantal graden te onttrekken.
Op deze pagina kun je eenvoudig “copy & paste” voorbeelden vinden, welke je in het script gedeelte kan zetten van een object.
Het voorbeeld uit het forum is gemaakt in SU2013, ik heb deze omgezet in SU 2015
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 |
ratio = 0 if ratio < 0 # Geef gegevens aan de linkerkant weer. logLine("Hendel status: " + sprintf("%.2f", ratio).to_s) logLine("Hendel hoek: " + sprintf("%.2f", theta.radians).to_s) 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 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 |
# Script for hinge, servo, motor, and corkscrew. onStart { # Find connected joint @joint_parent = nil @joint = nil @joint_name = nil parent_joints = this.group.get_attribute("SPOBJ", "parentJoints").to_a parent_joints.each { |jname| if jname =~ /hinge|servo|motor|corkscrew/i @joint_name = jname break end } if @joint_name # Find joint group associated with joint name Sketchup.active_model.entities.each { |e| next unless e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance) if e.get_attribute('SPJOINT', 'name', '') == @joint_name @joint = e else found = false e.entities.each { |ec| if ec.is_a?(Sketchup::Group) && ec.get_attribute('SPJOINT', 'name', '') == @joint_name @joint_parent = e @joint = ec found = true break end } break if found end } end if @joint # Get min/max data associated with the joint min = @joint.get_attribute('SPJOINT', 'min', 0).to_f max = @joint.get_attribute('SPJOINT', 'max', 0).to_f @range = (max - min).degrees # Calculate starting angle if @joint_parent tra = @joint_parent.transformation * @joint.transformation else tra = @joint.transformation end @init_dir = tra.xaxis.transform(this.group.transformation.inverse) @init_angle = min.degrees end } onUpdate { if @joint # Calculate object angle and ratio if @joint_parent tra = @joint_parent.transformation * @joint.transformation else tra = @joint.transformation end dir = @init_dir.transform(this.group.transformation).transform(tra.inverse).normalize # Get theta from -PI to PI theta = -Math.acos(dir.x) theta = -theta if dir.y < 0 ratio = @range.zero? ? 0 : (theta - @init_angle).to_f / @range ratio = 0 if ratio < 0 # Geef gegevens aan de linkerkant weer. logLine("Hendel status: " + sprintf("%.2f", ratio).to_s) logLine("Hendel hoek: " + sprintf("%.2f", theta.radians).to_s) logLine("") logLine("") logLine("") logLine("") logLine("") end } onEnd { } |
Gegevens naar seriële poort schrijven
Om nu de gegevens 0.00 t/m 1.00 naar de arduino te schrijven via de seriële poort, heb je de volgende Ruby code nodig in de volgende blokken onder “scripted”:
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 |
# Wat moet er gebeuren bij het starten van de simulatie? onstart{ compoortopties = ["Serial Port:", "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, "Serial port settings:") 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 } |
1 2 |
# Schrijf de data weg naar de seriele poort @serial.write(sprintf("%.2f", ratio).to_s) |
1 2 |
# Sluit de seriele poort als deze open staat. @serial.close if @serial |
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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# Script for hinge, servo, motor, and corkscrew. 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 # Find connected joint @joint_parent = nil @joint = nil @joint_name = nil parent_joints = this.group.get_attribute("SPOBJ", "parentJoints").to_a parent_joints.each { |jname| if jname =~ /hinge|servo|motor|corkscrew/i @joint_name = jname break end } if @joint_name # Find joint group associated with joint name Sketchup.active_model.entities.each { |e| next unless e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance) if e.get_attribute('SPJOINT', 'name', '') == @joint_name @joint = e else found = false e.entities.each { |ec| if ec.is_a?(Sketchup::Group) && ec.get_attribute('SPJOINT', 'name', '') == @joint_name @joint_parent = e @joint = ec found = true break end } break if found end } end if @joint # Get min/max data associated with the joint min = @joint.get_attribute('SPJOINT', 'min', 0).to_f max = @joint.get_attribute('SPJOINT', 'max', 0).to_f @range = (max - min).degrees # Calculate starting angle if @joint_parent tra = @joint_parent.transformation * @joint.transformation else tra = @joint.transformation end @init_dir = tra.xaxis.transform(this.group.transformation.inverse) @init_angle = min.degrees end } onUpdate { if @joint # Calculate object angle and ratio if @joint_parent tra = @joint_parent.transformation * @joint.transformation else tra = @joint.transformation end dir = @init_dir.transform(this.group.transformation).transform(tra.inverse).normalize # Get theta from -PI to PI theta = -Math.acos(dir.x) theta = -theta if dir.y < 0 ratio = @range.zero? ? 0 : (theta - @init_angle).to_f / @range # Soms kan de waarde kleiner zijn als nul (bij hard trekken aan het object) # zorg daarom dat deze niet onder de nul komt. ratio = 0 if ratio < 0 # Geef de gegevens weer aan de linker zijde (log). logLine("COM poort: " + $comport.to_s) logLine("BAUD rate: " + $baudrate.to_s) logLine("") logLine("Hendel status: " + sprintf("%.2f", ratio).to_s) logLine("Hendel hoek: " + sprintf("%.2f", theta.radians).to_s) logLine("") logLine("") logLine("") # Schrijf de data naar de seriele poort. @serial.write(sprintf("%.2f", ratio).to_s) end } # Wat moet er gebeuren als de de simulatie stopt? onend{ # Sluit de seriele poort als deze open staat. @serial.close if @serial } |
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 - 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