NGALAC/Subsystems

From Noisebridge
Revision as of 15:04, 1 April 2018 by Rando (talk | contribs) (Software)
Jump to navigation Jump to search

Power

Streaming PC

BIOS setting for Auto-on with power-on (e.g. from switch)

Audio

Gainclones are a DIY version of a $3000 audio system called the GainCard.

NGALAC possesses a LM3886TF based dual supply amp which requires a split rail +28/-28 DC supply

Amazon Link

LM3886TF based gainclone amp


Example DIY circuits which are easy to build with clear instructions

Example Circuits

Snubbed regulated PSU

Example PSU design

DIY PSU price is very high, will compare to purchase options
Using computer PSU may be possible after boosting +/-12 to +/-28, however, current on -12V line may not be enough to rate maximum wattage


Possible DIY Design
Qty Short Name Price Part Link Part Total
1 Transformer Dual 28V secondaries, 4.6A Max current $28.00 VPS56-2300 Digikey $28.00
16 Diode $1.00 MUR860 Digikey $16.00
4 Linear Voltage Regulator $2.10 LM338T Digikey $9.00
8 Rectifier Diode $0.20 LM4002 Digikey $1.60
4 1200uF Radial Aluminum Electrolytic Caps $1.00 - $6.00 (depending on current) EEU-FS1J102B Digikey $24.00
* Various Caps and Resistors (1W) $10.00 * * $10.00
Total $95.00

Electrical

  • Ground everything and very well, especially anything the human touches.

OBS automation

inputs -> Arduino/RaspberryPi <-> CmdMessenger <-> Serial port <-> USB <-> streaming CPU <-> PyCmdMessenger <-> obs-wc-controller <-> obs


Guardian Process - Windows OBS restart automatically on fail strategy


OBS Web Socket Plugin Sets up a websocket API for OBS
obs-wc-rc Python library to interface with OBS websocket API
PyCmdMesssenger Python library for CmdMessenger using serial port
CmdMessenger for Arduino Arduino CmdMessenger library to communicate with PyCmdMessenger on server via serial port

OBS websocket plugin

Tools -> Websocket Plugin Tools -> Websocket Plugin

obs-wc-rc

Query and send commands to OBS from python (can theoretically control everything)

import asyncio                                                                  
from obswsrc import OBSWS                                                       
from obswsrc.requests import (ResponseStatus,                                   
                              StartStreamingRequest,                            
                              GetStreamingStatusRequest                         
                              )                                                 
from obswsrc.types import Stream, StreamSettings                                
                                                                                
                                                                                
async def main():                                                               
                                                                                
    async with OBSWS('localhost', 4444, 'password') as obsws:                   
                                                                                
        response = await obsws.require(GetStreamingStatusRequest())             
                                                                                
        print("Streaming: {}".format(response.streaming))                       
        print("Recording: {}".format(response.recording))                       
                                                                                
                                                                                
loop = asyncio.get_event_loop()                                                 
loop.run_until_complete(main())                                                 
loop.close()


Output:

Streaming: False
Recording: True

Event Listener


import asyncio                                                                  
import logging                                                                  
import sys                                                                      
                                                                                
from obswsrc import OBSWS                                                       
from obswsrc.logs import logger                                                 
                                                                                
                                                                                
# We will output logging to sys.stdout, as many events might raise errors          
# on creation (that's because protocol.json is not perfect) - such errors          
# are logged by obs-ws-rc automatically, we just need to see them               
logger.setLevel(logging.ERROR)                                                  
logger.addHandler(logging.StreamHandler(stream=sys.stdout))                     
                                                                                
                                                                                
async def main():                                                               
                                                                                
    async with OBSWS('localhost', 4444, "password") as obsws:                   
                                                                                
        print("Connection established.")                                        
                                                                                
        # We will receive events here by awaiting for them (you can await for   
        # an event of a specific type by providing `type_name` argument to         
        # the obsws.event() method)                                             
        event = await obsws.event()                                             
                                                                                
        # Awaited event might be None if connection is closed                   
        while event is not None:                                                
            print("Awaited for '{}' event!".format(event.type_name))            
            event = await obsws.event()                                         
                                                                                
        print("Connection terminated.")

loop = asyncio.get_event_loop()                                                 
loop.run_until_complete(main())                                                 
loop.close()

Output:

Awaited for 'TransitionBegin' event!
Awaited for 'SwitchScenes' event!
Awaited for 'RecordingStarting' event!
Awaited for 'StreamStarting' event!

Arduino

Arduino code using CmdMessenger library for talking through serial port to python orchestrator

#include "CmdMessenger.h"

/* Define available CmdMessenger commands */
enum {
    ping,
    pong,
    player,
    lights,
    get_state,
    ret_state,
    error
};

unsigned long debounce[3] = {0, 0, 0};
unsigned long btn_state[3] = {LOW, LOW, LOW};
unsigned long bounce_delay = 75;

int input_pins[3] = {2, 3, 4};
int pressure_btn = 0;
int stream_btn = 1;
int pin = 0;
int output_pins[3] = {5, 6, 7};
int light_state = LOW;

/* Initialize CmdMessenger -- this should match PyCmdMessenger instance */
const int BAUD_RATE = 9600;
CmdMessenger c = CmdMessenger(Serial,',',';','/');

/* Create callback functions to deal with incoming messages */

void do_pong(void){
    c.sendCmd(pong, "pong");
}

void is_player(void){
    c.sendBinCmd(player, (int)btn_state[pressure_btn]);
}

void blink_lights(void){
    light_state = ~light_state;

    for(pin=0; pin<3; pin++) {
        digitalWrite(output_pins[pin], light_state);
    }
}

void send_state(void){
    c.sendCmdStart(ret_state);
    for(pin=0; pin<3; pin++) {
        c.sendCmdBinArg(digitalRead(input_pins[pin]));
    }
    for(pin=0; pin<3; pin++) {
        c.sendCmdBinArg(digitalRead(output_pins[pin]));
    }
    c.sendCmdEnd();
}

void on_unknown_command(void){
    c.sendCmd(error,"Command without callback.");
}

/* Attach callbacks for CmdMessenger commands */
void attach_callbacks(void) {
    c.attach(ping, do_pong);

    c.attach(player, is_player);
    c.attach(lights, blink_lights);
    c.attach(get_state, send_state);
    c.attach(on_unknown_command);
}

void read_btns(void) {
    int reading;

    for(pin=0; pin<3; pin++) {
        reading = digitalRead(input_pins[pin]);
        if (reading != btn_state[pin]) {
            debounce[pin] = millis();
        }
        if ((millis() - debounce[pin]) > bounce_delay) {
            if (reading != btn_state[pin]) {
                // Do something for that button, need butotn handlers
            btn_state[pin] = reading;
            }
        }
    }
}

void setup() {
    Serial.begin(BAUD_RATE);
    attach_callbacks();
    for(pin=0; pin<3; pin++) {
        pinMode(input_pins[pin], INPUT);
        pinMode(output_pins[pin], OUTPUT);
        digitalWrite(output_pins[pin], LOW);
    }
}

void loop() {
    c.feedinSerialData();
    read_btns();
}


Python code to pair with CmdMessenger

import PyCmdMessenger                                                           
                                                                                
arduino = PyCmdMessenger.ArduinoBoard("/dev/ttyUSB0", baud_rate=9600)           
                                                                                
commands = [['ping', ''],                                                       
            ['pong', 's'],                                                      
            ['player', 'i'],                                                    
            ['lights', ''],                                                     
            ['get_state', ''],                                                  
            ['ret_state', 'i*'],                                                
            ['error', '']]                                                      
                                                                                
c = PyCmdMessenger.CmdMessenger(arduino, commands)                              
                                                                                
c.send('ping')                                                                  
msg = c.receive()                                                               
print(msg)                                                                      
                                                                                
c.send('player')                                                                
print(c.receive())                                                              
                                                                                
#  Turn On Lights                                                               
c.send('lights')                                                                
                                                                                
c.send('get_state')                                                             
msg = c.receive()                                                               
print(msg)                                                                      
                                                                                
#  Turn off Lights                                                              
c.send('lights')                                                                
c.send('get_state')                                                             
msg = c.receive()                                                               
print(msg)                                                                      
                                                                                
controls = msg[1]                                                               
if controls[0] != 0:                                                            
    print("Start Stream!")

output from running python controller

Connecting to arduino on /dev/ttyUSB0... done.
('pong', ['pong'], 1522043014.6538415)
('player', [0], 1522043014.6666553)
('ret_state', [1, 0, 1, 1, 1, 1], 1522043014.704131)
('ret_state', [1, 0, 1, 0, 0, 0], 1522043014.744068)
Start Stream!

First 3 states are switches set high or low

Last 3 are LED states (or anything else)

Can trigger LED strips or whatever else as we wish, run pre-defined patterns, etc.


Software

Arduino IDE 1.8.1+
* CmdMessenger
Python 3.5.4+
* vitualenv, virtualenvwrapper-win, PyCmdMessenger, obs-ws-rc
Git

notes:

evtest to check inputs from the IPAC-2 on rpi

add player 2 keys to retropi retroarch config

swap out audio receiver for car amp thing

test autio streaming with mic, cabinet audio, and stream audio

found a woofer to test with (tbd)

usb shit - polling on rpi

keep alives for obs, obs restart on power on, rpi watchdog, faulover OBS instance, switched by obswsrc cannot connect. how will this work with auto start, and how to select which instance is stealing?

impedance matching circuit

rpi watchdog

static electricity on case

Arduino COM port detection on streaming PC in python