Hi,
I’m currently running into a problem trying to implement an Arduino switch.
I have an Arduino that listens on it’s serial interface to receive Strings and then swicht something. So far so good. I can use the serial monitor in arduino IDE to send strings and get responses. The same goes for plain python from the powershell.
In SweepMe I adapted an existing Arduino Switch (Arduino Display) and adapted it to do a self.port.read() in initialize() and read again in reach to catch a response.
If I run this from a sequencer with two valid Strings in the sweepBox I get: “serial.serialutil.PortNotOpenError: Attempting to use a port that is not open” I checked if the COM port was in use by something else, which seems not to be the case. In that case I get: “serial.serialutil.SerialException: could not open port ‘COM3’: PermissionError(13, ‘Zugriff verweigert’, None, 5)”
I also tried to adapt to adapt the comport_pyserial.py example from the script tool, which returns an empty byte string eventhough there should be something in the buffer from starting up the arduino.
Does anyone have a clue where this port issue might be originating from?
Hi,
it is difficult to say what is the reason as the error messages do not provide much information rather than saying the port is not open.
You can have a look at our Arduino driver guide:
https://wiki.sweep-me.net/wiki/Arduino_Driver_guide
where we deschribe how to create a SweepMe! driver for Arduino and how to setup the Arduino.
Two important things are:
The Arduino should send an automatic initialization message at the beginning that can be used by the SweepMe! driver to know that commands can be processed from now on. Further, the Arduino code should use
Serial.readStringUntil('\n')
to read a string from the com port buffer. Using “\n” with double quotation marks does not work.
Can you check this and come back to us if there is still a problem?
Here is what I use in setup():
// Start Serial to communicate to SweepMe!
Serial.begin(9600);
Serial.println("Started Switch Box");
In loop():
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim();
int pin = getPinFromString(command.c_str());
if (pin > 0) { //valid input
reset_all_relais();
digitalWrite(pin, HIGH);
delay(500);
digitalWrite(pin, LOW);
Serial.println("Turned on " + command);
}
else {
Serial.println("Error!");
}
Hi,
the code looks good and I guess you have tried the typical things like, restarting SweepMe! to free any closed COM port, reconnecting the Arduino etc.
Did you update SweepMe! to the latest version (1.5.6.24)?
Did you close the Serial Monitor in the Arduino IDE? It does not work in SweepMe! if the Serial Monitor is still open or if any other program has access to the open COM port.
Best, Axel
Hi Axel,
it is a fresh install of 1.5.6.24.
I did try a restart of SweepMe! and also a full System reboot. I also tried replugging the nano and also restarting it while plugged in to receive a new message to the serial buffer.
As initially mentioned I get a different error if the com port is used by another process.
Hi,
is it possible to share your driver here?
Best, Axel
Sure, I’ll just drop it as a code snippet:
from EmptyDeviceClass import EmptyDevice
class Device(EmptyDevice):
description = """Send a string to an 16x2 LCD display via an Arduino."""
def __init__(self):
EmptyDevice.__init__(self)
self.shortname = "Arduino Switch Box"
self.port_manager = True
self.port_types = ["COM"]
self.port_properties = { "baudrate": 9600,
"timeout": 2,
}
def get_GUIparameter(self, parameter={}):
self.clear_at_end = parameter["Clear after run"]
def set_GUIparameter(self):
GUIparameter = {
"SweepMode" : ["Display text"],
"Display": ["16 characters, 2 rows"],
"Clear after run": True,
}
return GUIparameter
def initialize(self):
try:
response = self.port.read()
print(f"Received: {response}\n")
except:
print("Exception")
def deinitialize(self):
pass
def apply(self):
self.port.write(str(self.value))
print(f"Sent: {self.value}\n")
def reach(self):
# readout of the response related to the previous apply must be in reach!!
# sometimes apply is not called, e.g. if the value to be set would be 'nan'
# as reach is only called if also apply was called, one can be sure that
# both function are called pairwise.
response = self.port.read()
print(f"Received: {response}\n")
The .ino for the Arduino:
#define RESET_PIN 12
#define P11 9 //P1-1
#define P12 8 //P1-2
#define P13 7//P1-3
#define P14 6 //P1-4
#define P21 5 //P2-1
#define P24 2 //P2-4
#define P23 3 //P2-3
#define P22 4 //P2-2
struct PinMapping {
const char* name;
int pin;
};
// Define Pin mapping
PinMapping mapping[] = {
{"P11", 9},
{"P12", 8},
{"P13", 7},
{"P14", 6},
{"P21", 5},
{"P22", 2},
{"P23", 3},
{"P24", 4}
};
const int numMapping = sizeof(mapping) / sizeof(mapping[0]);
void setup() {
// put your setup code here, to run once:
pinMode(RESET_PIN, OUTPUT);
pinMode(P11, OUTPUT);
pinMode(P12, OUTPUT);
pinMode(P13, OUTPUT);
pinMode(P14, OUTPUT);
pinMode(P21, OUTPUT);
pinMode(P22, OUTPUT);
pinMode(P23, OUTPUT);
pinMode(P24, OUTPUT);
// Reset all Relais
reset_all_relais();
// Start Serial to communicate to SweepMe!
Serial.begin(9600);
Serial.println("Started Switch Box");
}
void loop() {
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim();
int pin = getPinFromString(command.c_str());
The code looks good and should work in my oppinion.
One further guess: SweepMe! allows to use GPIB adapters from Prologix where the user can register a COM port via menu “File” → “Options” → “Ports”. If somebody uses such an adapter at your setup and has registered a COM port there, it could generate a conflict with opening the COM port in your case.
A way to further debug the driver or the problem is to use the object
self.port.port
https://wiki.sweep-me.net/wiki/Port_manager#Communication
Starting from the semantic phase function “connect” the driver has access to the object self.port which is a SweepMe! port object wrapping different communication interfaces.
With self.port.port you can access the underlying port object, e.g. from pyserial or pyvisa. It means that you have a look whether the port is open and do some modifications for testing purposes.
Also have a look at this issue with a similar COM port problem:
I got it working in the end.
Turned out to be a timeout issue. My setup() started the serial port at the end after a lengthy function call (reset_all_pins()), leading to the serial port not being available within the timeout set in the driver.
I moved the initialization of the serial port to the beginning of setup(), which solved the issue:
void setup() {
// put your setup code here, to run once:
// Start Serial to communicate to SweepMe!
Serial.begin(9600);
Serial.println("Started Switch Box");
pinMode(RESET_PIN, OUTPUT);
pinMode(P11, OUTPUT);
pinMode(P12, OUTPUT);
pinMode(P13, OUTPUT);
pinMode(P14, OUTPUT);
pinMode(P21, OUTPUT);
pinMode(P22, OUTPUT);
pinMode(P23, OUTPUT);
pinMode(P24, OUTPUT);
// Reset all Relais
reset_all_relais();
}