looking for a simple relay controller

To be more specific, check out:

phidgets.com/?tier=3&catid= … rodid=1020
4 SPDT relays 210W for DC or 1750VA for AC, they have one with 8 relays on board as well. Controlled from a simple API in C, C#, Java, JS, Python, Max/MSP, Obj-C, .NET, and Swift

thanks everyone.

hi drhandshake,
Are you saying ‘pure python’ as in you have only used outside of Touch?
We got the Phidget relay here you pointed to. I’ve managed to get it working in a 3.5.1 Idle environment and am now trying to weed through the one example script I found relevant to the relay (Digital_output.py).
it would be great if somebody has actually got this to work in Touch and slimmed down the example script to just the essentials it takes to actually control the relay in Touch.

If you used within Touch, was this 088 or 099? what version of Python ?
regards,
c.o’d

Hey yeah I meant the project I did with that relay was a python-only application …

I think probably the easiest way to deal with a device like that is to run the relay handling stuff in a standalone (python, javascript, whatever) process and communicate with it from TD over sockets or whatever suits you.

We use the Phidget Python module directly inside TouchDesigner and haven’t seen any issues. Relays a pretty easy to interface with as you are just setting values

The challenging part is using the devices that allow you to set a callback. They run on a separate thread and TD will complain or crash if you reference any TD objects. Best solution I’ve found is to open a socket to a tcpip dat from within the callback and send the callback args back via a json dict.

Yes - to clarify - the callback stuff is the use case I was recommending a separate thread for. IIRC the Phidgets handler keeps a connection open to the device and sends an ack when coms are established so if you don’t want to keep re-opening that for every change you could run that in a standalone context and communicate to it from your main TD process.

Recently used this. (with OSC)
shop.pimoroni.com/products/automation-hat + a Pi
The code is here (but not latest version PM me if you are interested)
github.com/jpkelly/autopi
Also had to hack the Automation Hat library a bit based on this post.
forums.pimoroni.com/t/automatio … issue/6692

I use ESP’s for everything now.

you can get pre-packaged chips that work just like arduino, I like the D1 Mini series.

amazon.com/IZOKEE-NodeMcu-I … ds=d1+mini

just like arduino they come with all sorts of shields

[url]https://www.amazon.com/Diymore-ESP8266-Development-Shield-Arduino/dp/B01N9KG234/ref=sr_1_1?ie=UTF8&qid=1548708397&sr=8-1&keywords=d1+mini+relay[/url]

and with a little bit of code you can connect it to Touch in a few minutes.

I also use OSC for things like this.

[ below is arduino code ]


#include <WiFiUdp.h>
#include <ESP8266WiFi.h>
#include <OSCMessage.h>
#include <OSCBundle.h>

WiFiUDP Udp;                                // A UDP instance to let us send and receive packets over UDP

IPAddress outIp(10, 0, 1, 5);     // remote IP of your computer
const unsigned int outPort = 9900;          // remote port to receive OSC
const unsigned int localPort = 9901;        // local port to listen for OSC packets (actually not used for sending)

const char* ssid     = "[YOUR SSID OF WIFI]";
const char* password = "[THE WIFI PASSWORD]";

unsigned int ledState = LOW;              // LOW means led is *on*

void setup() {
  pinMode(D1, OUTPUT);
  digitalWrite(D1, ledState);

  Serial.begin(115200);
  delay(100);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  
  Serial.println("Starting UDP");
  Udp.begin(localPort);
  Serial.print("Local port: ");
  Serial.println(Udp.localPort());
  server.begin();
}

void oscMessage(int input) {
  Serial.print("oscMessage()");
  OSCMessage msg("/esp");
  msg.add(input);
  Udp.beginPacket(outIp, outPort);
  msg.send(Udp);
  Udp.endPacket();
  msg.empty();
  delay(50);
}

void relay(OSCMessage &msg, int addrOffset ) {
  ledState = msg.getInt(0);
  digitalWrite(D1, ledState);
  Serial.print("/led: ");
  Serial.println(ledState);
   oscMessage(ledState);
}

void loop() {
 OSCMessage msgIN;
  int size;
  if ( (size = Udp.parsePacket()) > 0)
  {
    while (size--)
      msgIN.fill(Udp.read());
    if (!msgIN.hasError()) {
      msgIN.route("/relay", relay);
    }
    outIp = Udp.remoteIP();
  } 
}

in touch, use an OSCOUT dat and run this script

op('oscout_relay').sendOSC('/relay',[1])

or this one

op('oscout_relay').sendOSC('/relay',[0])

Heres something I literally threw together in 10 minutes.

[url]https://photos.app.goo.gl/kUkHgcjHfreXy5DP7[/url]

well my partner went with phidget relay so I’m tasked with figuring out, finding it to be a bit beyond me.

I’ve been hacking away at ‘DigitalOutput’ example script with intention of running in CHOPEXECUTE DAT, got standalone script below working with a hard-wired address in IDLE3.5.1, but within Touch099 its unreliable and slow. I’m not fully clear on open vs. attach channel requirements in script.

If any phidget users could point to a bare-minimum script for Touch I’d be much obliged. I cant seem to pare it down to what is essential with all the exceptions and support for usb hub/network stuff.

[code]#import sys
import time
#import traceback
from Phidget22.Devices.DigitalOutput import *
from Phidget22.PhidgetException import *
from Phidget22.Phidget import *
from Phidget22.Net import *

‘’‘try:
from PhidgetHelperFunctions import *
except ImportError:
sys.stderr.write(“\nCould not find PhidgetHelperFunctions. Either add PhdiegtHelperFunctions.py to your project folder "
“or remove the import from your project.”)
sys.stderr.write(”\nPress ENTER to end program.")
readin = sys.stdin.readline()
sys.exit()’‘’

‘’’

  • Displays info about the attached Phidget channel.

  • Fired when a Phidget channel with onAttachHandler registered attaches

  • @param self The Phidget channel that fired the attach event
    ‘’’
    def onAttachHandler(self):

    ph = self
    try:
    #If you are unsure how to use more than one Phidget channel with this event, we recommend going to
    #Using Multiple Phidgets - Phidgets Support for information

      print("\nAttach Event:")
      
      """
      * Get device information and display it.
      """
      serialNumber = ph.getDeviceSerialNumber()
      channelClass = ph.getChannelClassName()
      channel = ph.getChannel()
      
      deviceClass = ph.getDeviceClass()
      if (deviceClass != DeviceClass.PHIDCLASS_VINT):
          print("\n\t-> Channel Class: " + channelClass + "\n\t-> Serial Number: " + str(serialNumber) +
                "\n\t-> Channel:  " + str(channel) + "\n")
      else:            
          hubPort = ph.getHubPort()
          print("\n\t-> Channel Class: " + channelClass + "\n\t-> Serial Number: " + str(serialNumber) +
                "\n\t-> Hub Port: " + str(hubPort) + "\n\t-> Channel:  " + str(channel) + "\n")
    

    except PhidgetException as e:
    print(“\nError in Attach Event:”)
    DisplayError(e)
    traceback.print_exc()
    return
    “”"

  • Displays info about the detached Phidget channel.

  • Fired when a Phidget channel with onDetachHandler registered detaches

  • @param self The Phidget channel that fired the attach event
    “”"
    def onDetachHandler(self):

    ph = self
    try:
    #If you are unsure how to use more than one Phidget channel with this event, we recommend going to
    #Using Multiple Phidgets - Phidgets Support for information

      print("\nDetach Event:")
      
      """
      * Get device information and display it.
      """
      serialNumber = ph.getDeviceSerialNumber()
      channelClass = ph.getChannelClassName()
      channel = ph.getChannel()
      
      deviceClass = ph.getDeviceClass()
      if (deviceClass != DeviceClass.PHIDCLASS_VINT):
          print("\n\t-> Channel Class: " + channelClass + "\n\t-> Serial Number: " + str(serialNumber) +
                "\n\t-> Channel:  " + str(channel) + "\n")
      else:            
          hubPort = ph.getHubPort()
          print("\n\t-> Channel Class: " + channelClass + "\n\t-> Serial Number: " + str(serialNumber) +
                "\n\t-> Hub Port: " + str(hubPort) + "\n\t-> Channel:  " + str(channel) + "\n")
    

    except PhidgetException as e:
    print(“\nError in Detach Event:”)
    DisplayError(e)
    traceback.print_exc()
    return

“”"

  • Writes Phidget error info to stderr.

  • Fired when a Phidget channel with onErrorHandler registered encounters an error in the library

  • @param self The Phidget channel that fired the attach event

  • @param errorCode the code associated with the error of enum type ph.ErrorEventCode

  • @param errorString string containing the description of the error fired
    “”"
    def onErrorHandler(self, errorCode, errorString):

    sys.stderr.write(“[Phidget Error Event] → " + errorString + " (” + str(errorCode) + “)\n”)

“”"

  • Creates, configures, and opens a DigitalOutput channel.

  • Provides interface for setting the duty cycle of the DigitalOutput channel

  • Closes out DigitalOutput channel

  • @return 0 if the program exits successfully, 1 if it exits with errors.
    “”"
    def main():

    ch = DigitalOutput()

    ch.setDeviceSerialNumber(499892)
    ch.setHubPort(0)
    ch.setIsHubPortDevice(0)
    ch.setChannel(0)

    print(“\nSetting OnAttachHandler…”)
    ch.setOnAttachHandler(onAttachHandler)

    print(“Setting OnDetachHandler…”)
    ch.setOnDetachHandler(onDetachHandler)

    print(“Setting OnErrorHandler…”)
    ch.setOnErrorHandler(onErrorHandler)

    ch.openWaitForAttachment(5000)
    ch.setDutyCycle(1.0)
    time.sleep(3)
    ch.setDutyCycle(0.0)
    time.sleep(3)
    ch.setDutyCycle(1.0)

main()

[/code]

Can you send a .toe showing how you have this set up?

Looks like it’s attaching callbacks to a persistent connection to the device after some blocking calls (sleep), both of which are a bad fit for running within your main TD instance – this is why I was suggesting you might want to run this code in a freestanding Python process and communicate to it from your TD process with sockets or whatever suits.

thks Noah et al,

I guess I’m stubbornly not accepting the idea that most hardware that is Python controllable really is best controlled outside of touch’s internal python environment. Seems counter-intuitive and wasteful, complicating, but I guess any ‘performance hit’ ( if it exists) even in the most critical situations is probably largely unnoticeable. I need to just accept this and master JSON, OSC or UDP etc. communication to external Python ‘nodes’(if that is even the right term) :neutral_face: (Ive done this sort of communication before and it worked efficiently, but now Ive forgotten most of it and will have to re-familiarize myself)

also, explaining to somebody who is even a lesser programmer than me ’ yeah, you got to run this Python script outside of Touch simultaneously…’
( ‘First-World problems’, I know … )

It does seem like most of the suggested hardware solutions in this thread come to the same conclusion.
Maybe it is better this way, rather than trying to always adapt Python/hardware code to run in Touch … that way all I have to do is adapt whatever code to receive JSON or the like …

how to run a python file:

go to terminal/cmdprompt (outside of Touch)

type "python [path/name of file .py] "

press “return” or “enter”


it seems like you are making this a lot more complicated with sub-process python scripts connecting to serial lines. I would try to reduce the number of components adding complexity to this system you are making.

A simple wireless relay with a boolean message sent over OSC is my simplest recommendation.

heres one for 8 bucks.
amazon.com/IZOKEE-Wireless- … 8266+relay

thks Harvey I ordered one to check out . 8 bucks is a no-brainer.

the customer reviews seem to suggest there was hardware issue that has been resolved by manufacturer?

also is the cable in this vid just to provide power through USB to the ESP?

matthew could you/ would you be willing to share script ? I’ve not been able to make this work purely inside touch. im using 004 relay unit - hope that is what u are using.

So, the $8 one will probably take some more effort to program. you will need a usb adapter in order to connect to it over serial USB.

or, looks like amazon has that too.

amazon.com/diymore-ESP8266- … programmer

Then you will be able to re-program the esp with custom code that talks directly to touch.

I would recommend however, the first post I made. with the D1 Mini.
amazon.com/Makerfocus-Devel … 145&sr=8-3

It is a better chip because it comes with a USB port for easy programming
( and yes power also, the code uploads through the cable, but the code I use only transmits over wifi. In the video you can also see serial debugging messages that are sent over USB in a different program showing on my screen, this is just for debugging.

I usually use them attached to phone USB power chargers, but you can also just wire up a wall-wart)

you would plug this ESP into this relay, and you are off to the races.

amazon.com/HiLetgo-Relay-Sh … mini&psc=1

you can buy these chips and the relays for 1/8th of the price on Aliexpress

https://www.aliexpress.com/item/D1-mini-Mini-NodeMcu-4M-bytes-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266-by/32651747570.html

thank you @harveymoon for the post!
i just stumbled over it and having an ESP32s i tried your script. But i am new to the arduino world and it gave me the following errors (see below)
If i understand correctly it loads something called ESP8266WiFi.h whcih in my case should be
ESP32Wifi.h i guess :unamused:
what can i do to make the thing run ?!

ERROR FROM ARDUINO:
Multiple libraries were found for “WiFiUdp.h”
osc01:2:25: error: ESP8266WiFi.h: No such file or directory
Used: /Users/bst/Library/Arduino15/packages/esp32/hardware/esp32/1.0.1/libraries/WiFi
compilation terminated.
Not used: /private/var/folders/d4/wt5z02692j79hhy5t05dk4_40000gr/T/AppTranslocation/BB700A48-4FC1-4DCA-B445-EC97B56BE04F/d/Arduino.app/Contents/Java/libraries/WiFi
Not used: /private/var/folders/d4/wt5z02692j79hhy5t05dk4_40000gr/T/AppTranslocation/BB700A48-4FC1-4DCA-B445-EC97B56BE04F/d/Arduino.app/Contents/Java/libraries/WiFi
Not used: /private/var/folders/d4/wt5z02692j79hhy5t05dk4_40000gr/T/AppTranslocation/BB700A48-4FC1-4DCA-B445-EC97B56BE04F/d/Arduino.app/Contents/Java/libraries/WiFi
Not used: /private/var/folders/d4/wt5z02692j79hhy5t05dk4_40000gr/T/AppTranslocation/BB700A48-4FC1-4DCA-B445-EC97B56BE04F/d/Arduino.app/Contents/Java/libraries/WiFi
exit status 1
ESP8266WiFi.h: No such file or directory

Sure! No problem.

You’ll need to install the phidget python module and point TD toward the 64bit python module path of course.

The parameters are pretty straight forward, you’ll just need to enter the serial number of the device and choose the correct Hub Port and Channel. If you have it connected to a usb VINT hub you’ll want to make sure the “Remote Device” toggle is off. That’s only for use with the SBC4. Once you have the parameters set correctly, use the “Open Channel” pulse to connect.

The HUB Port Device parameter should be off if you’re using a VINT relay module. That switch is for connecting a digital out directly to the hub port.

Just wanted to say a little more about this: We have used every option listed on this thread and have decided that Phidgets are by far the best choice. I’ve had plenty failures with ESPs, Teensys, Arduinos, Raspberry PIs, Pi Plates, and a few other serial relays. Never once have we had to replace a Phidget on a job. Some of our Phidgets have been running for +1year on permanent installations.

In addition to that, the setup time is non-existent. Their products are plug and play there is no soldering/coding/pulling-hair-out needed. Most products are even fitted with screw terminals. We have a tox file for almost every product of theirs and use them on virtually every job we do.

The product design is very well thought through, their software is wonderful, and their price points are very reasonable. We keep a fully stocked cabinet of their products and have pretty much given away most of the other devices we have used in the past.

For me and the rest of the crew at VT, Phidgets are the definitive answer.
digitalOutputPhidget.tox (1.89 KB)

1 Like

Reviving an old thread here, but does the above tox and explanation work with Phidget’s Power Plug product?

Yep it definitely should.

1 Like

Hi Matthew,

I’m trying to follow along. I really struggled to receive data from a Phidget RFID read-write device. I picked one up after seeing your recommendation here on the forum.

(Initially I was getting a module not found error. I’m not Python proficient. At first I wasn’t sure how exactly to point TD toward the 64bit python module, but I figured it out finally in the TD > Preferences pane. Should I leave “Search External Python Path Last” enabled?)

Using your rfidPhidget.tox from the other thread, I wasn’t sure how to get it connected to the device. I stumbled my way through and am succesfully connected and reading tags!

I thought I’d share how I managed to do this for the sake of others. I entered the correct PhidgetRFID serial number. ‘Remote Device’ should remain disabled. ‘Callbacks Port’ remains 7014 for me. And pulse ‘Open Channel’. Then ‘Is Open’ should change from false to true! Now the device should automatically read when a tag is near/on the device.

Phidget Control Panel can remain open, but do not open the Phidget RFID device “channel”, otherwise it will conflict with Touch and won’t open a connection.

What does the ‘Remote Device’ toggle do? For a different type of Phidget RFID device other than USB?

Any guidance would be greatly appreciated!