add artnet

This commit is contained in:
interfisch 2025-05-06 22:54:04 +02:00
parent bc9e06ba03
commit c3a4b00682
3 changed files with 209 additions and 8 deletions

120
movinghead/artnetSend.py Normal file
View file

@ -0,0 +1,120 @@
import socket
import struct
import time
import math
class ArtNet():
packet_counter = 1
dmxdata = [0, 0]
def __init__(self, artnet_net, artnet_subnet, artnet_universe, ip, port):
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.net = int(artnet_net)
self.subnet = int(artnet_subnet)
self.universe = int(artnet_universe)
self.ip = ip
self.port = int(port)
print(self.port)
#logger.debug("Init ArtNet Plugin done")
def run(self):
pass
def stop(self):
self.close()
def __call__(self, var1=None, var2=None):
if type(var1) == int and type(var2) == int:
self.send_single_value(var1, var2)
if type(var1) == int and type(var2) == list:
self.send_frame_starting_at(var1, var2)
if type(var1) == list and type(var2) == type(None):
self.send_frame(var1)
def send_single_value(self, adr, value):
if adr < 1 or adr > 512:
#logger.error("DMX address %s invalid" % adr)
return
while len(self.dmxdata) < adr:
self.dmxdata.append(0)
self.dmxdata[adr - 1] = value
self.__ArtDMX_broadcast()
def send_frame_starting_at(self, adr, values):
if adr < 1 or adr > (512 - len(values) + 1):
#logger.error("DMX address %s with length %s invalid" %
# (adr, len(values)))
return
while len(self.dmxdata) < (adr + len(values) - 1):
self.dmxdata.append(0)
cnt = 0
for value in values:
self.dmxdata[adr - 1 + cnt] = value
cnt += 1
self.__ArtDMX_broadcast()
def send_frame(self, dmxframe):
if len(dmxframe) < 2:
#logger.error("Send at least 2 channels")
return
self.dmxdata = dmxframe
self.__ArtDMX_broadcast()
def __ArtDMX_broadcast(self):
# logger.info("Incomming DMX: %s"%self.dmxdata)
# New Array
data = []
# Fix ID 7byte + 0x00
data.append("Art-Net\x00")
# OpCode = OpOutput / OpDmx -> 0x5000, Low Byte first
data.append(struct.pack('<H', 0x5000))
# ProtVerHi and ProtVerLo -> Protocol Version 14, High Byte first
data.append(struct.pack('>H', 14))
# Order 1 to 255
data.append(struct.pack('B', self.packet_counter))
self.packet_counter += 1
if self.packet_counter > 255:
self.packet_counter = 1
# Physical Input Port
data.append(struct.pack('B', 0))
# Artnet source address
data.append(
struct.pack('<H', self.net << 8 | self.subnet << 4 | self.universe))
# Length of DMX Data, High Byte First
data.append(struct.pack('>H', len(self.dmxdata)))
# DMX Data
for d in self.dmxdata:
data.append(struct.pack('B', d))
# convert from list to string
result = bytes()
for token in data:
try: # Handels all strings
result = result + token.encode('utf-8', 'ignore')
except: # Handels all bytes
result = result + token
self.s.sendto(result, (self.ip, self.port))
def close(self):
self.s.close()
if __name__ == '__main__':
artnet_subnet = 0
artnet_net = 0
artnet_universe = 1
ip = '195.160.169.161'
port = 6454
sh = ArtNet(artnet_net, artnet_subnet, artnet_universe, ip, port)
value = 0
while True:
#sh.send_single_value(1,value)
#sh.send_frame([128,0,128,0])
sh.send_frame([128,int(128+math.sin(value/50.0*10)*120),128,int(128+math.cos(value/50.0*10)*120)])
time.sleep(1.0/50)
value +=1

View file

@ -21,6 +21,7 @@ monitor_speed=115200
lib_deps =
waspinator/AccelStepper@^1.64
hideakitai/ArtNet@^0.8.0
build_flags =
-D EN_PIN=D0

View file

@ -1,11 +1,22 @@
#include <Arduino.h>
#include <AccelStepper.h>
#include <ESP8266WiFi.h>
#include <ArtnetWiFi.h>
// https://learn.watterott.com/de/silentstepstick/pinconfig/tmc2130/
const char* ssid = "wifi";
const char* password = "password";
ArtnetWiFiReceiver artnet;
uint16_t universe1 = 1; // 0 - 32767
uint8_t net = 0; // 0 - 127
uint8_t subnet = 0; // 0 - 15
uint8_t universe2 = 2; // 0 - 15
// Motor / Hardware Configuration
int microsteppingPan = 4;
@ -17,6 +28,8 @@ int microsteppingTilt = 4;
long stepsPerRotationTilt=microsteppingTilt*42*400/12; //12z to 42z
long homepos_tilt=0; //positive number=homed position is too far clockwise
double aimTilt=360; //in degrees
double aimPan=360;
enum Mode{
PROGRAM,
@ -61,6 +74,7 @@ float mapfloat(float x, float in_min, float in_max, float out_min, float out_max
void testMovementPan();
void testMovementTilt();
void testCircle();
void movePosition();
bool isEndstopPan();
bool isEndstopTilt();
@ -105,9 +119,9 @@ void setStepperPreset(Stepperpreset preset,Stepper s)
break;
case NORMAL:
pan_speed=stepsPerRotationPan*1/4;
pan_accel=stepsPerRotationPan*1/2;
pan_accel=stepsPerRotationPan*1;
tilt_speed=stepsPerRotationTilt*1/4;
tilt_accel=stepsPerRotationTilt*1/2;
tilt_accel=stepsPerRotationTilt*2;
break;
case FAST:
//abs. max. speed w/o load: stepsPerRotationPan*2/3 @19V
@ -130,6 +144,61 @@ void setStepperPreset(Stepperpreset preset,Stepper s)
}
}
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
void initArtnet(){
artnet.begin(); // waiting for Art-Net in default port
//artnet.subscribeArtDmxUniverse(universe15bit, [&](const uint8_t *data, uint16_t size, const ArtDmxMetadata &metadata, const ArtNetRemoteInfo &remote) {
// if Artnet packet comes to this universe(0-15), this function is called
//});
// if Artnet packet comes to this universe, this function (lambda) is called
artnet.subscribeArtDmxUniverse(universe1, [&](const uint8_t *data, uint16_t size, const ArtDmxMetadata &metadata, const ArtNetRemoteInfo &remote) {
/*Serial.print("lambda : artnet data from ");
Serial.print(remote.ip);
Serial.print(":");
Serial.print(remote.port);
Serial.print(", universe = ");
Serial.print(universe1);
Serial.print(", size = ");
Serial.print(size);
Serial.print(") :");
for (size_t i = 0; i < size; ++i) {
Serial.print(data[i]);
Serial.print(",");
}
Serial.println();*/
if (size>=4){
aimPan=( (data[0]<<8) +data[1])/65535.0*720;
aimTilt=( (data[2]<<8) +data[3])/65535.0*720;
Serial.print("aimPan="); Serial.print(aimPan);
Serial.print(" aimTilt="); Serial.print(aimTilt);
Serial.println();
}
if (size>=5) {
setOutput(data[4]>127);
}
});
// you can also use pre-defined callbacks
//artnet.subscribeArtDmxUniverse(net, subnet, universe, callback);
//artnet.subscribeArtDmxUniverse(0, 0, 0, callbackArtnet);
}
void setup() {
Serial.begin(115200);
@ -139,7 +208,11 @@ void setup() {
setOutput(false);
pinMode(EN_PIN,OUTPUT);
setEnable(false);
delay(500); //wait until terminal ready
initWiFi(); //195.160.169.161
initArtnet();
//stepperPan.moveTo(stepsPerRotationPan/2);
@ -160,6 +233,7 @@ void setup() {
void loop() {
static unsigned long last_change;
artnet.parse();
// ### Mode handling ###
switch(mode){
@ -179,7 +253,8 @@ void loop() {
case RUN:
//testMovementPan();
//testMovementTilt();
testCircle();
//testCircle();
movePosition();
break;
case IDLE:
@ -205,9 +280,9 @@ void loop() {
switch(mode){
case PROGRAM:
Serial.print("PAN Endstop="); Serial.print(digitalRead(ENDSTOP_PAN));
/*Serial.print("PAN Endstop="); Serial.print(digitalRead(ENDSTOP_PAN));
Serial.print(" TILT Endstop="); Serial.print(analogRead(ENDSTOP_TILT));
Serial.println();
Serial.println();*/
break;
case HOME:
@ -247,8 +322,8 @@ void setMode(Mode newmode) {
break;
case RUN:
setStepperPreset(FAST,PAN); //set Pan
setStepperPreset(FAST,TILT); //set Tilt
setStepperPreset(NORMAL,PAN); //set Pan
setStepperPreset(NORMAL,TILT); //set Tilt
setEnable(true);
mode=newmode;
Serial.println("Mode set to RUN");
@ -382,6 +457,11 @@ void testMovementTilt()
}
}
void movePosition() {
stepperPan.moveTo(aimPan/360.0*stepsPerRotationPan);
stepperTilt.moveTo(aimTilt/360.0*stepsPerRotationTilt);
}
bool isEndstopPan()
{