Does Fusion 360 not have access to USB ports by default? - python

I'm working on making my own 3D mouse, sort of like 3D Connexion's own model. I'm using Autodesk's Fusion 360 as my application, and Fusion's API(Application Program Interface) to interact with the mouse. I have a gyroscope + accelerometer that spits raw measurements into an Arduino, which then sends those values(through the serial port using the Serial library). I'm then using the PySerial library(because Fusion's API uses python for it's language) to read that data coming from the Arduino, and spit it into Fusion, where I can control the camera position. The issue that I'm running into is that, for testing, I can print the values of the gyro + accelerometer to the Command Prompt just fine with a Python script. But when I try the exact same script in Fusion's code editor(Spyder), it doesn't work. I know that the Serial library is being imported, but the script doesn't work. Is it possible that Fusion 360 doesn't have access to the USB ports? If so, how could I fix it?
Here is a little snipet of my code:
#This is a python script that when run in the CMD, it works just fine.
import serial
ser = serial.Serial()
ser.baudrate = 9600
ser.port = 'COM3'
ser.open()
while True:
result = ser.readline()
result = str(result)
print (result)
All that this code does, is it reads the value of a potentiometer hooked up to an Arduino. It then prints those values into the CMD.
Here is the code that comes from the Fusion 360 API:
#This is the Fusion 360 code that doesn't work.
import adsk.core, adsk.fusion, adsk.cam, traceback
import serial
def get(app):
try:
ui = app.UserInterface
ser = serial.win32.Serial()
ser.baudrate = 9600
ser.port = 'COM3'
ser.open()
value = ser.read()
value = str(value)
adsk.doEvents()
ui.messageBox(value)
except:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def Main():
try:
app = adsk.core.Application.Get()
ui = app.UserInterface
ui.messageBox("Everything is working till this point")
adsk.doEvents()
get(app)
except:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Main()
exit()
Thanks in advance!

In answer to your question, it may be so that Fusion360 does not have access to serial ports directly.
Fusion360 has a JavaScript API available and had to add custom calls to allow access to local machine resources like files.
(JavaScript does not have that natively).
That may be the nature of the problem you are up against, even though your program is written in Python. (I think F360 uses its JavaScript API to display its own User Interface).
Also, I see a difference between the code snippets:
ser = serial.win32.Serial()
...
ser = serial.Serial()
Perhaps you can call the first program from F360, and simply write to a file or something like that, to test it.

Related

Arduino pyfirmata analog reading problems

I am having some problems reading analog values from my Arduino Mega using pyfirmata.
I use Arduino Mega with a Mega Sensor Shield.
I would like to read analog values from a HW-201 IR sensor (pin A5).
I have uploaded the Standard firmata sketch on Arduino IDE, and I am running the following code using Anaconda Spyder:
import serial
import serial.tools.list_ports
from pyfirmata import ArduinoMega, util
from time import sleep
def readArduinoPort():
COM = []
ports = list(serial.tools.list_ports.comports())
for p in ports:
if "Arduino" in p.description:
COM.append(str(p.device))
return COM
COM = readArduinoPort()
board = ArduinoMega(COM[0])
pin = board.get_pin('a:5:i')
it = util.Iterator(board)
it.start()
try:
while True:
print(pin.read())
sleep(0.1)
except KeyboardInterrupt:
pass
Now, this code runs just fine the first time I use it, generating numbers close to 1 when the sensor is detecting proximity and numbers close to 0 when not detecting anything.
However, whenever I try to run the Iterator a second time (without restarting the kernel), the code generates seemingly random numbers (almost like the pin was floating, like nothing was connected to it).
Any idea why this is happening? Is this a normal behavior?
Thank you!
I already checked these questions that do not entirely address my issue:
arduino pyfirmata analog reading
Analog readings on Arduino returns wrong values
I have the same result by not having anything pinned to pin A5 of the Arduino Mega.
I wasn't sure, but I tried adding:
board.analog[5].enable_reporting()
before the iterator and then:
board.analog[5].disable_reporting()
but nothing changed.
Board Differences
I ran into the same problem. I own both a Mega and an Uno and needed to select the appropriate Board and Processor in the tools menu:
Tools > Board > _board_
Tools > Processor > _processor_

How to send an API frame to a remote XBee using Digi XBee Python module?

I am moving code from Python XBee library to Digi's Python XBee library and I am unable to locate syntax in the docs on how to send a API frame to a remote XBee. I am using S1 and S1 Pro devices where the "local" device is attached to a Beaglebone and the "remote" devices are standalone out in the wild.
I have the basic framework down:
from digi.xbee.devices import XBeeDevice, RemoteXBeeDevice, XBee64BitAddress
PORT = '/dev/ttyO1'
BAUD = 9600
API_FRAME = 'long-hex-string-here'
local_xbee = XBeeDevice(PORT, BAUD)
local_xbee.open()
# Instantiate a remote XBee device object.
remote_xbee = RemoteXBeeDevice(local_xbee, XBee64BitAddress.from_hex_string("0013A20040DD7DCD"))
# Transmit frame to remote_xbee - unsure of correct method and syntax
# perhaps XBeePacket.create_packet(hex string here)
# local_xbee.send_data(remote_xbee, "api frame here?") ??
local_xbee.close()
but I am unable to locate syntax for how to transmit my constructed API frame. Based upon the Introduction section in the docs I presume that is the correct approach. I am not interested in broadcasting to all devices on the network but rather unicast communication.
I have some older model of the source when I could get it to work.
…
I have some WiFi Xbee modules that I used w/ some converter boards (base boards). I used it to attach the communication of the Xbee from one computer to another, e.g. random desktop to BeagleBone Black via USB instead of UART. So, I would use the source, listed below, to attach my USB dongle for the Xbee communication from the BBB to the other field module.
Their I/O stuff can be found here: https://github.com/digidotcom/xbee-python/tree/master/examples/io.
Also...changing just some of their lines in their source w/ the USB dongle WiFi adapter boards proved valuable in signaling LEDs and other sensors.
Oh and you will need what they are now calling Carrier Boards. It is the adapter board I just typed out. So, if you have already got a Carrier Board, use lsusb as the command in Linux to find your USB "name."
So, for instance, if lsusb brings up /dev/ttyUSB0, then that is the port identification.
And you can use that section, from lsusb, to then change your xbee modules in the xtcu software from Digi.
…
from digi.xbee.devices import XBeeDevice
from digi.xbee.io import IOLine, IOMode
import time
import threading
# TODO: Replace with the serial port where your local module is connected to.
PORT = "/dev/ttyUSB0"
# TODO: Replace with the baud rate of your local module.
BAUD_RATE = 9600
REMOTE_NODE_ID = "Xbee_B"
IOLINE_IN = IOLine.DIO2_AD2
IOLINE_OUT = IOLine.DIO4_AD4
def main():
print(" +-----------------------------------------------+")
print(" | XBee Python Library Get/Set Remote DIO Sample |")
print(" +-----------------------------------------------+\n")
stop = False
th = None
local_device = XBeeDevice(PORT, BAUD_RATE)
try:
local_device.open()
print("local device: ", local_device.get_node_id())
# Obtain the remote XBee device from the XBee network.
xbee_network = local_device.get_network()
remote_device = xbee_network.discover_device(REMOTE_NODE_ID)
if local_device is None:
print("Could not find the remote device")
exit(2)
def io_detection_callback():
while not stop:
# Read the digital value from the input line.
io_value = remote_device.get_dio_value(IOLINE_IN)
print("%s: %s" % (IOLINE_IN, io_value))
# Set the previous value to the local output line.
local_device.set_dio_value(IOLINE_OUT, io_value)
time.sleep(2)
th = threading.Thread(target=io_detection_callback)
remote_device.set_io_configuration(IOLINE_IN, IOMode.DIGITAL_IN)
local_device.set_io_configuration(IOLINE_OUT, IOMode.DIGITAL_OUT_HIGH)
time.sleep(1)
th.start()
input()
finally:
stop = True
if th is not None and th.is_alive():
th.join()
if local_device is not None and local_device.is_open():
local_device.close()
if __name__ == '__main__':
main()
So, see the PORT = "/dev/ttyUSB0" section of the source?
This is where I attached my Xbee module to the Carrier Board and then attached the Carrier Board to the BBB by way of USB.
Um, this may not answer a question but give more insight as to how to handle Digi Devices/Modules.
I also think that if you want to venture in this direction of UART communication w/ Xbee and the BeagleBone Black, it may be more complicated. I will keep searching my text.
P.S. This book goes over some methods to connect, Experiment 10 and Experiment 16, your "BBB" to a UART, Xbee, and how to communicate. It is a bit too in depth to get all of the communication ideas from this book but this is it:
The Hands-on XBEE Lab Manual, Experiments that Teach you XBEE Wireless Communications – Jonathan A Titus

Connecting RS232 to Serial and establishing a connection to Nextion display from a python script

I was trying to establish a serial communication between my python script and Nextion display.
I want to create a custom firmware uploader, so I could use it instead of Nextion Editor.
Unfortunately I can't establish a connection to the screen(RS232 to Serial is connected properly and detected, I use default 9600 baud rate).
After sending
DRAKJHSUYDGBNCJHGJKSHBDNÿÿÿ
connectÿÿÿ
ÿÿconnectÿÿÿ
It should respond properly...
I found a document from Nextion that explains the Upload Protocol: https://nextion.tech/2017/12/08/nextion-hmi-upload-protocol-v1-1/
And here is my script, that produces from time to time
b'$\xff\xff\xff'
import serial
from time import sleep
ser = serial.Serial('/dev/tty.usbserial-A94RJPXT',9600,timeout=0)
ser.write(str.encode(" DRAKJHSUYDGBNCJHGJKSHBDNÿÿÿ"))
ser.write(str.encode("\n"))
ser.write(str.encode(" connectÿÿÿ"))
ser.write(str.encode("\n"))
ser.write(str.encode(" ÿÿconnectÿÿÿ"))
ser.write(str.encode("\n"))
while True:
print(ser.readline())
sleep(0.1)
WORKING CODE:
import serial
from time import sleep
ser = serial.Serial('/dev/tty.usbserial-A94RJPXT',9600,timeout=0)
ser.write("DRAKJHSUYDGBNCJHGJKSHBDNÿÿÿ".encode('iso-8859-1'))
ser.write("connectÿÿÿ".encode('iso-8859-1')) # could try some other encodings
ser.write("ÿÿconnectÿÿÿ".encode('iso-8859-1'))
while True:
data=ser.readline().decode('iso-8859-1')
if data !="":
print(data)
sleep(0.1)
If you look at this GitHub commit, you'll see that they do:
this->sendCommand("DRAKJHSUYDGBNCJHGJKSHBDNÿÿÿ");
this->sendCommand("connectÿÿÿ");
this->sendCommand("ÿÿconnectÿÿÿ");
That suggests that you do not need the spaces or newlines. If that doesn't work, you should also consider different encodings (and make your current encodings explicit):
ser.write("DRAKJHSUYDGBNCJHGJKSHBDNÿÿÿ".encode('utf-8'))
ser.write("connectÿÿÿ".encode('utf-8')) # could try some other encodings
ser.write("ÿÿconnectÿÿÿ".encode('utf-8'))

pyserial: how to receive rs232 answers from power supply correctly

I'm currently trying to set up a communication with a power supply (RND 320-KA3005P) through RS232 with pyserial.
The Problem is that after sending "*DIN?", which should return manufacturer, model name and software version, the connection seems to receive nothing. Also no other command was successful. Using the included software, after connecting, a LabView program opens and the device is remote controllable, so I think the problem is in my code.
Code Example:
Connection parameters as described in the manual.
As end-of-line characters I tried "\r\n","\r","\n" which seems to solve many other problems, but here with no success.
import io
import serial
import time
import sys
ser = serial.Serial('COM4',
baudrate = 9600,
bytesize=8,
timeout=1,
stopbits = serial.STOPBITS_ONE,
parity = serial.PARITY_NONE,
xonxoff = False)
eol_char = '\r\n'
sio = io.TextIOWrapper(io.BufferedReader(ser),newline=eol_char)
while True:
sending = input("type:\n")
ser.write((sending + eol_char).encode('utf-8'))
time.sleep(0.2)
ans = sio.read()
sys.stdout.write('received: ' + str(ans))
print('\ntry again\n')
Which after entering the command gives:
type:
*DIN?
received:
try again
type:
Also when I run the script on the loopback
ser = serial.serial_for_url('loop://',timeout=1)
...
output:
type:
*DIN?
received: *DIN?
try again
type:
it seems to work fine. I'm using Windows 10 and a USB to RS232 converter. Does anyone have an idea about what I'm missing here?
Thanks in advance.
The solution I figured out is rather disappointing. Turns out that with a USB to RS232 converter cable, instead of the USB connection I used before, the commands to set and get values work as expected. The command '*DIN?', which I tried initially, which I got from the manual:), still gives no reaction - probably just not supported.
I believe the *DIN? command, found under "Functionality check" which should return: "Manufacturer, model name, software version.", is actually a typo. When all commands are later listed in the manual, number 11 says *IDN? and should return the KA3005P identification.
It is also ironic that the example they give under number 11 says: "* IDN?"...

Port already in use

I am on a Windows 7 computer, trying to use Python to run a simple program on my Arduino to make it blink.
For some reason, whenever I attempt to run the script in PowerShell, I receive an error that the port is already open. I have tried restarting my computer, changing Arduinos, changing the USB port that I have plugged into, running a different program that I am quite sure closes the computers connection to the port. However, I am still getting the same error.
I am quite new to Python and Arduino, so there might be something stupidly easy that I am forgetting. I have asked a friend who is more experienced and he spoke of it being a problem with Windows.
Here is the relevant code. The class I used in Python is as follows.
import serial
import socket
import glob
import pickle
from time import sleep,time
class Ardustat():
def __init__(self):
self.port = ""
self.ser = serial.Serial()
self.mode = "serial"
self.debug = False
def findPorts(self):
"""A commands to find possible ardustat ports with no Arguments, """
return glob.glob("COM*")
def connect(self,port):
if self.mode == "serial":
self.ser = serial.Serial(port,57600)
self.ser.timeout = 1 # what does this do?
self.ser.open()
return "connected to serial"
And the Python code is
from ardustat_library_simple_dan import Ardustat
import time
serial_port = 'COM6'
ard = Ardustat()
#Connect to the irritating ardustat
ard.connect(serial_port)
for a in range(0,5):
ard.blink(serial_port)
time.sleep(.2)
The Arduino code is long, but in the setup there is the following code.
void setup()
{
//Startup Serial
Serial.begin(57600);
// Serial.println("Hi Dan!");
Is there anything wrong?
I can see a few reasons why this is not working:
You have your serial monitor running while you're running your script:
The serial port can only be open once on a given host, if you try to open it twice, the second program to open it will report it as already opened.
You did not open the serial connection on the Arduino side:
You say you run a blink sketch. If that's the default blink.ino, it does not open the serial port and your system may report the serial port is not openable (and I don't know Windows, but I wouldn't be surprised to see an inconsistent error happening)
You wrote your own blink sketch, but you did not put Serial.begin(115200); in the setup() of your sketch file.
You open the port twice (or more) in the Python code.
You shall have only one serial.open() statement in your code.
So first, check your code to be sure you do actually use the serial port from within the Arduino sketch. You can paste your code in your question so we can check that out.
Then, check your Python code to be sure you do actually open the serial port once and only once within your script.
Finally, be sure to not have another program opening the serial port while you're running your script, usually one tend to test the connection with Arduino's serial monitor, let it open and try to open the port using a script, which does not work. I saw that very often from beginners.
And I vote for... problem #3 \o/
class Ardustat():
def __init__(self):
self.port = ""
self.ser = serial.Serial() # Here you open the port once
self.mode = "serial"
self.debug = False
def findPorts(self):
"""A commands to find possible ardustat ports with no Arguments, """
return glob.glob("COM*")
def connect(self,port):
if self.mode == "serial":
self.ser = serial.Serial(port,57600) # Here you open the port twice
I did not check pySerial's source code, but I'm pretty sure serial.Serial() opens up the first serial port it finds available at its default speed. Therefore, as you don't close the connection from the first instance of self.ser, the second instance gets crazy saying "dude, it's already opened!".
That's why you'd better not add an abstraction (Artustat) over a correct abstraction (pyserial.Serial), but just use correctly the tools and do something like:
with serial.Serial(port, speed) as ser:
do_blink(ser)
where do_blink() is a function where you do your stuff. The with statement over serial.Serial will take care of the life of the serial port object (opening it when you enter the block, closing it as you exit the block).

Categories

Resources