Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
babyeatingpsychopath
Oct 28, 2000
Forum Veteran


Sockser posted:

Having trouble googling what I want here

I have built some basic FFT visualizers out of a raspi, like, raspi is running audio and visualizing it

What I want to build, via some flavor of arduino, is a board that will accept a 3.5 audio in and then let me process that, but I can only find audio output boards, or schematics that use a microphone rather than a direct line in. Is there some sort of arduino breakout that exists that will just let me do the thing I want without having to build out my own circuit for this?

An arduino can take line-in directly to its ADC. Just need a few components to get DC bias in the middle of the range, set the swing, and then use whatever lib you want. So "build your own circuit" yes, but it's just resistors and capacitors and maybe a potentiometer unless your line-in is well-behaved.

I found http://wiki.openmusiclabs.com/wiki/ArduinoFFT and http://wiki.openmusiclabs.com/wiki/ArduinoFHT as audio->frequency converters, and both libriaries are set up to use either a separate ADC or the ATMEGA's own ADC.
Their brand of "separate ADC" is available as a you-solder-it kit https://synthcube.com/cart/open-music-labs/open-music-labs-codecshield-kit.

babyeatingpsychopath fucked around with this message at 17:36 on Nov 28, 2021

Adbot
ADBOT LOVES YOU

ToxicFrog
Apr 26, 2008


Nearly a year after moving, I finally found the box I packed all my electronics parts into, including three Arduinos in various form factors (one of which I'm pretty sure is dead following an incident with the bathroom sink, oh well) and and two NTC CHIPs, which are ARMv7 based single-board linux machines, kind of like stripped down RPi2s.

Unlike the Pi2, they have integrated wifi, so I'm considering setting them up as remote indoor temperature sensors -- probably one in the basement near the spider enclosures, and one upstairs somewhere. Since they run linux I can just install munin-node on them and integrate them into my overall monitoring network, without needing to figure out how to write a munin node implementation on an arduino or something.

Anyone else here used the CHIP for anything?

Sockser
Jun 28, 2007

This world only remembers the results!




"ADC" was the obvious term I was not looking for :facepalm:

Bought a Teensy shield that'll do what I want, plus it lets me use a Teensy, woo.

Hadlock
Nov 9, 2004

Data Graham
Dec 28, 2009

📈📊🍪😋



Love that "Oh poo poo" :hmmyes:

Sockser
Jun 28, 2007

This world only remembers the results!




Working on some LED projects right now

Right now I've got a 5v supply running to my LEDs and the ground connected to my Teensy.
When I release this from programming mode and go to power the Teensy via the 5v supply, it's bad for it to be connected via both USB and an external 5v supply, right? There's a trace I'm supposed to cut?

Cojawfee
May 31, 2006
I think the US is dumb for not using Celsius
You can also get data only USB cables if this isn't going to be a permanent installation.

babyeatingpsychopath
Oct 28, 2000
Forum Veteran


Sockser posted:

Working on some LED projects right now

Right now I've got a 5v supply running to my LEDs and the ground connected to my Teensy.
When I release this from programming mode and go to power the Teensy via the 5v supply, it's bad for it to be connected via both USB and an external 5v supply, right? There's a trace I'm supposed to cut?

There is a link to cut. It's location depends on the Teensy model you have. You can also let the fuse do its job and blow if the current imbalance is over half an amp. Note that this might be bad for your USB supply or your power supply.

ToxicFrog
Apr 26, 2008


Just did my first experiment with CircuitPython (on a Gemma M0, reading a 3-axis magnetometer over I²C and changing the colour of an LED based on it) and goddamn, this is really, really nice. Pretends to be a USB mass storage device when plugged in, so you don't even have a separate flashing step, just edit the python code directly on the device and reboot it. Gives you a serial console (with repl!) on /dev/ttyUSB0. And the Gemma even has a tiny RGBLED surface mounted to it so I could quickly hack something together using it before getting out the neopixel strips.

I had to write my own HMC5883L driver to talk to the sensor, but even with that this is a much nicer UX than loving around with the Arduino tooling.

Hedningen
May 4, 2013

Enough sideburns to last a lifetime.
Glad this thread is here: I’m reworking a project that I’ve been trying to finish for ages, and I doubtlessly will have a few stupid questions when I hit a wall.

As a general question: is FSM a good case for a boardgame scoreboard? I’ve been hacking together a Blood Bowl scoreboard, and I realized that I was already half-assedly running it as a FSM by only looking for input from certain pins when certain conditions were met via a bunch of badly-written functions and nested loops. So, hoping to formalize it by reading into state-based design.

My general map looks like six states (PREGAME, TURNOVER, P1, P2, HALF_END, and GAME_END), with TURNOVER acting as a switching station between states in order to handle things more smoothly. lovely diagram of how I see looping through:



So, to make sure I’m doing this correctly:
1) Are state transitions meant to be another state (i.e my logic that says “Go from PREGAME to TURNOVER” is held in a state called transition?
2) For more complex state change behavior, is it just using if/ifelse loops within the state itself? (I.e in HALF_END, if half == max_half and p1score = p2score, check if playoffs == true and change to GAME_END if playoffs =/= true, but iterate half otherwise, or do I need to create separate states?
3) States should be set to wait until input is received or until calcs run, correct?
4) When setting states, you can maintain stuff like displays without having to re-run the logic everywhere, right? As I’m running a bunch of 7-segment displays through a pair of MAX7219s along with OLED screens that really won’t change that much, I want to keep things looking as even as possible.

Bonus terrible wiring shot from my initial tests.

Fanged Lawn Wormy
Jan 4, 2008

SQUEAK! SQUEAK! SQUEAK!
Hey ! I think I can help with this one. I do a lot of Arduino-based stuff for exhibits and games, and almost all are FSM-like in orientation.

First: My personal preference is to run the FSM as a big Switch() statement. I also setup an Enum early in the program and name my states, ie: PREGAME, TURNOVER, etc, so that I can visually read it very easily. I

Hedningen posted:

So, to make sure I’m doing this correctly:
1) Are state transitions meant to be another state (i.e my logic that says “Go from PREGAME to TURNOVER” is held in a state called transition?
2) For more complex state change behavior, is it just using if/ifelse loops within the state itself? (I.e in HALF_END, if half == max_half and p1score = p2score, check if playoffs == true and change to GAME_END if playoffs =/= true, but iterate half otherwise, or do I need to create separate states?
3) States should be set to wait until input is received or until calcs run, correct?
4) When setting states, you can maintain stuff like displays without having to re-run the logic everywhere, right? As I’m running a bunch of 7-segment displays through a pair of MAX7219s along with OLED screens that really won’t change that much, I want to keep things looking as even as possible.

1) Kind of depends on how complex you want it to be. I've generally found that it helps me to make a set of simple functions to call for transitions. They tend to get used in multiple places, and that way I can keep them consistent. Off the top of my head, you might have functions like UpdatePlayerScore(), ResetScore(), etc.

2) Eh, I think that's fine, if I'm reading it right.

3) Think of each state as a self-contained loop that is only worrying about what is necessary for that state. So, your "p1" state is only worrying about player 1's inputs, player 1's score, and whatever conditions may end that player's turn.

4) Yep! This one is probably easiest to give you in pseudo-code. Here's how I would do something like that:

code:
loop()
{
BlinkLed();

switch(GameState)
{
case PREGAME:
//do a cool animation at game start, play a sound, whatever
break;

case
Turnover:
//change players
break;

case PLAYER_ONE:
//read input buttons
//update score variable (?)
//check to see if turn is over
break;
etc etc etc

}

}
I this example, I always have the BlinkLED() function running, which acts as a heartbeat for my controller. It's an easy thing to have a client check when troubleshooting over the phone. So, that function is probably something like this:
code:
if(myChrono.haspassed(200){
     if(isLEDon){
          digitalWrite(LEDPIN, LOW)
          } else
          {
          digitalWrite(LEDPIN, HIGH)
           }
isLEDon = !isLEDon
}
BTW, if you aren't using the Chrono (or the older version, Metro) library already, get it, it'll make things like this a lot easier.

As for things like Displays, etc - most of the screens and libraries I've dealt with will basically keep whatever they were told until they are told to do something else. So, if you tell it to display a 5, there's no reason to tell it to display a 5 again. So, you might make your score updating a function that happens when the event to change the score happens, and only do it then. Now, if you are doing a something like a cute animation on the screen continuously, that'll need to be more like the BlinkLED example above.

Foxfire_
Nov 8, 2010

If it were me, I would not use explicit states for the topmost logic like that. The main thing you're using state machines for is so that other stuff can keep running while you wait for something to happen (e.g. you don't want something like while (IsButtonPushed()) to block everything else). One component can have its functions block though, as long as it pokes everything else while its waiting. Nothing else blocks so nothing else can be stuck waiting for it.

For explanatory purposes, consider a thing with a display, a speaker, and a button that does this:
- The display shows a turn counter in the corner always
- When you hold the button, it displays a pair of animated rolling dice and plays a continuous dice rolling noise
- When you release the button, it shows a random dice result. If it's double skulls, it plays a sad trombone once and advances the turn counter
- After turn 16, the turn counter resets
- The display and speaker need periodic software attention to load new DAC samples/video frames
(Our players are very bashy and have no interest in anything besides punching)

I would do this like:

- Make code modules for the display, buttons, and speaker. Each of them has an Update() function that deals with their 'time just passed' logic and a bunch of functions for changing what they are doing or asking them questions. None of these functions can block. The implementation of those may involve some small state machines, depending on what exactly they need to do (e.g. a button debouncer can probably just be some flags and a time-until-stable count; a speaker might want some enumerated states for things like silent/looping sound/single sound/crossfades).

code:
//---------------------------------------------------
// Do one instance of periodic processing for button
// debouncing
//---------------------------------------------------
void Button_Update(void);

//---------------------------------------------------
// Test if the button is currently pressed (after 
// debouncing it)
//---------------------------------------------------
BOOL Button_IsPressed(void);

//---------------------------------------------------
// Do one instance of periodic processing for the display
// (e.g. load next frame of animation if its time)
//---------------------------------------------------
void Display_Update(void);

//---------------------------------------------------
// Update the turn counter
//
// Parameters:
// [in]turnCount    New turn count
//---------------------------------------------------
void Display_SetTurnCount(int turnCount);

//---------------------------------------------------
// Start showing the dice animation. The frames will
// be updated by `Display_Update()` as time passes
//---------------------------------------------------
void Display_StartDiceAnimation(void);

//---------------------------------------------------
// Stop any dice animation and show some results
//
// Parameters:
// [in]dice1    First dice
// [in]dice2    Second dice
//---------------------------------------------------
void Display_ShowDice(BlockDice dice1, BlockDice dice2);


//---------------------------------------------------
// Do one instance of periodic processing for the speaker
// (e.g. load more samples for the audio DAC if we're
// playing something)
//---------------------------------------------------
void Speaker_Update(void);

//---------------------------------------------------
// Stop playing any sounds
//---------------------------------------------------
void Speaker_Silent(void);

//---------------------------------------------------
// Start playing continuous dice rolling noises.  
// Future `Speaker_Update()` will keep loading more
// samples as needed
//---------------------------------------------------
void Speaker_StartContinuousDiceRolling(void);

//---------------------------------------------------
// Start playing the sad trombone once.  This doesn't
// wait until the sound finishes, it queues stuff up.
// (Any SW processing that has to happen for it in the future
// will be done in `Speaker_Update()` [like if the sound didn't
// fit in a DAC buffer and needed to get loaded in pieces
// as it played out)
//---------------------------------------------------
void Speaker_StartSadTrombone(void);

//---------------------------------------------------
// Test if we've finished playing sounds
//---------------------------------------------------
BOOL Speaker_IsSilent(void);
- Have a 'make time pass' function that does some waiting then pokes everything's Update()
- The main logic can then go into normal functions using normal control structures and stack variables. It doesn't need to return as long as it calls the time passing function at every point it waits. This makes it a lot easier to read & write because all the flow is together instead of needing to constantly return, reenter, figure out what it was doing, and save temporaries somewhere outside function locals.

code:
//--------------------------------------------------------------------
// Advance time one tick, then do all 'time passes' periodic updating
//--------------------------------------------------------------------
void AdvanceTime(void)
{
  // Optionally do some kind of waiting here.  Either spin on a timer, a wait-for-event
  // instruction with a wakeup event configured, or go fast if you're doing some other
  // kind of timekeeping instead of periodic ticks
  SomeKindOfWait();
  
  // Update everything that needs periodic updating
  Button_Update();
  Display_Update();
  Speaker_Update();
}

//--------------------------------------------------------------------
// Main game logic.  This /doesn't/ need to return quickly (or ever) 
// as long as it calls `AdvanceTime()` while it waits
//--------------------------------------------------------------------
void GameLogic(void)
{
  // Each loop will be one run through turns 1-16
  while (TRUE)
  {
    // Since we don't need to return every tick, we can use normal 
    // control structures instead of needing lots of enumerated
    // states or having mixed enumerated state+a bunch of stashed state data
    //
    // Could use normal stack locals too, but don't have any in this example
    // besides this turn counter
    for (int turnCount = 1; turnCount <= 16; ++turnCount)  
    {
      Display_SetTurnCount(turnCount);
      
      // Keep doing rolls for this turn until Nuffle is mad and we break out
      while (TRUE)
      {
        // Wait for start of roll
        while (!Button_IsPressed())
        {
          AdvanceTime();
        }
        
        // Start stuff for rolling, then wait for end of roll
        Display_StartDiceAnimation();
        Speaker_StartContinuousDiceRolling()
        while (Button_IsPressed())
        {
          AdvanceTime();
        }
        
        // Resolve the roll
        BlockDice dice1 = SomePreviouslyUnmentionedRngThatReturnsADiceEnum();
        BlockDice dice2 = SomePreviouslyUnmentionedRngThatReturnsADiceEnum();
        Display_ShowDice(dice1, dice2);
        Speaker_Silent();
        if ((dice1 == BLOCK_DICE__SKULL) && (dice2 == BLOCK_DICE__SKULL))
        {
          break;
        }
        
        // Loop for next roll
      }
      
      // Womp-womp
      //
      // (Don't let them start the next turn until sound is done)
      Speaker_StartSadTrombone();
      while (!Speaker_IsSilent())
      {
        AdvanceTime();
      }
      
      // Loop to next turn
    }
    
    // Got to turn 16, starting over
  }
}
It's effectively taking something with a traditional main loop like
code:
while (TRUE)
{
  SomeKindOfWait();
  Button_Update();
  Display_Update();
  Speaker_Update();
  GameLogic_Update();
}
and lifting the GameLogic part up to the top of the loop (since the top of the loop isn't doing anything otherwise)

Hedningen
May 4, 2013

Enough sideburns to last a lifetime.
Thank you both so much!

I’ll get things debugged a bit more, ensure that my hardware works, and then post some code this weekend, assuming I have time to get everything done. One initial issue was the cheap 7-segment displays I bought having different layouts than what I pulled into Fritzing, and having to update that so the display worked properly.

Already working on case design: thankfully have access to a nice laser cutter and a friend with a resin printer, so should be able to design a pretty good enclosure for my next stadium project.

Enos Shenk
Nov 3, 2011


Have you guys had one of those projects where it just refuses to work, and due to your own fuckups and unknown errors you just keep digging deeper? Yeah, I'm at that point. See, I had a couple NEMA17 stepper motors laying around. I also had an Adafruit Motor Shield laying around. So I figured I should make something neat with them. I settled on an analog clock with the hour and minute hands driven by seperate motors, with optical interrupters to detect a known "base" position like 12:00. The idea was the thing could reset to 12:00 at power on, then read a clock module and set the time.

I designed all the mechanical bits in Fusion 360 and 3d printed them, got everything slapped together and realized the steppers I had wouldn't work with the motor shield. So naturally I ordered new motors, and naturally hosed up and ordered the wrong ones. So now I have 4 stepper motors that won't work with the shield I already had.

So I did some digging, found A4988 stepper drivers on cute little breakout boards. Ordered some of those, built up a little circuit for them on a proto shield, and poo poo didn't work. Troubleshot that for a couple days until I was pulling my hair out and decided to order a nice little pre-made shield that just mounts them up. Got that, plugged everything together, and fried the gently caress out of my Uno trying to power both off one supply.

Order a new Uno, plug everything back together, run two seperate power supplies, and poo poo still doesn't work. So now I'm sitting on a dumb project that was mostly just to put some spare bits to use, and I've almost entirely replaced said spare bits. And I still have nothing to show for it.



At least the mechanical side looks good. Honestly I should just redesign the thing to use smaller lower power steppers, but that would be digging down.

Cojawfee
May 31, 2006
I think the US is dumb for not using Celsius

Enos Shenk posted:

Have you guys had one of those projects where it just refuses to work, and due to your own fuckups and unknown errors you just keep digging deeper?

Stop doxxing me

Wrr
Aug 8, 2010


Hey y'all, I got a project I'm working on and would like some feedback on. Real newbie question here.

The long and short of it is I am having to custom build a watchdog circuit. My watchdog circuit is primarily within a While() loop. Each loop it increments a timer value, and when that time value hits a configurable limit value, it executes a check on the devices the watchdog is for. If everything is fine, the timer value drops to 0, and it keeps going. If it detects an issue, the arduino throws some relays which power cycle the devices and hopefully clears the issue out.

I would like to add a push-button that allows the user to manually force a relay-reset. I was eyeballing the interrupt() functions, but I can't use delays within them and I want my relay to stay open for a few seconds (using delay(5000) atm) to ensure that there is a clean power break. What is the actual good way to do this? I have a feeling it may be "do not use a while() loop".

I thought about doing:

if(resetButton == HIGH){
while loop;
}

if(resetButton == LOW){
manual relay reset;
}

The button in this case, of course, is an INPUT_PULLUP that will get grounded.

I can post the full code if you'd like, although it is getting pretty beefy. I think to really clean it up I should break things out into discrete sub-functions but its fine for now, as far as I can tell. Also can show hardware setup in case you need to know, I've been posting about it in some other threads so maybe y'all have seen it already.

Edit:
Actually here is my code https://docs.google.com/document/d/1leGBxdLEtjbnf9NoxTFu9gRzj3WugfR4uPmm3fkoVRs/edit?usp=sharing

Wrr fucked around with this message at 18:16 on Jan 12, 2022

DC to Daylight
Feb 13, 2012

Wrr posted:

Hey y'all, I got a project I'm working on and would like some feedback on. Real newbie question here.

The long and short of it is I am having to custom build a watchdog circuit. My watchdog circuit is primarily within a While() loop. Each loop it increments a timer value, and when that time value hits a configurable limit value, it executes a check on the devices the watchdog is for. If everything is fine, the timer value drops to 0, and it keeps going. If it detects an issue, the arduino throws some relays which power cycle the devices and hopefully clears the issue out.

I would like to add a push-button that allows the user to manually force a relay-reset. I was eyeballing the interrupt() functions, but I can't use delays within them and I want my relay to stay open for a few seconds (using delay(5000) atm) to ensure that there is a clean power break. What is the actual good way to do this? I have a feeling it may be "do not use a while() loop".

I thought about doing:

if(resetButton == HIGH){
while loop;
}

if(resetButton == LOW){
manual relay reset;
}

The button in this case, of course, is an INPUT_PULLUP that will get grounded.

I can post the full code if you'd like, although it is getting pretty beefy. I think to really clean it up I should break things out into discrete sub-functions but its fine for now, as far as I can tell. Also can show hardware setup in case you need to know, I've been posting about it in some other threads so maybe y'all have seen it already.

Edit:
Actually here is my code https://docs.google.com/document/d/1leGBxdLEtjbnf9NoxTFu9gRzj3WugfR4uPmm3fkoVRs/edit?usp=sharing

There are a lot of ways you could handle this, but I would probably do something like this:

unsigned long TurnRelayBackOnTime;

if(resetButton == LOW){
TurnRelayBackOnTime = 5000 + millis() //or whatever

//code to turn relay off here
}

Somewhere in your main loop:
if(millis() > TurnRelayBackOnTime)
{
//code to turn relay on
}

Wrr
Aug 8, 2010


DC to Daylight posted:

There are a lot of ways you could handle this, but I would probably do something like this:

unsigned long TurnRelayBackOnTime;

if(resetButton == LOW){
TurnRelayBackOnTime = 5000 + millis() //or whatever

//code to turn relay off here
}

Somewhere in your main loop:
if(millis() > TurnRelayBackOnTime)
{
//code to turn relay on
}

Sorry but I don't quite follow this.

My main question is how to get the reset button to interrupt and do something during the While Loop. Are you suggesting that the TurnRelayBackOnTime gets set in the Interrupt function, and then essentially gets executed back in the main loop?

VictualSquid
Feb 29, 2012

Gently enveloping the target with indiscriminate love.
If your while loop is reasonably quick, you would normally set a global variable in the button interrupt and then check that variable within the big loop to actually do stuff.

Foxfire_
Nov 8, 2010

Does this device need to do anything besides be a watchdog?

DC to Daylight
Feb 13, 2012

Wrr posted:

Sorry but I don't quite follow this.

My main question is how to get the reset button to interrupt and do something during the While Loop. Are you suggesting that the TurnRelayBackOnTime gets set in the Interrupt function, and then essentially gets executed back in the main loop?

I probably wouldn't bother with an interrupt if you can avoid it - As VictualSquid said, if the rest of the loop is pretty quick, you'll catch the button press.

Sound_man
Aug 25, 2004
Rocking to the 80s
I'm looking for a two pole connector for a project. Low amps, 3.3V signal but I'd prefer something a little more rugged than JST I'd like something a little smaller and cheaper than an XLR connector but I haven't come across anything I like. I'd need two mating sets so anything that requires custom tooling is also out.

Anyone have a clever lead?

Wrr
Aug 8, 2010


Okay, so I did some reading on millis() and I get what you were saying.

I would ahead with the idea of putting the many body of code inside of if(ResetButton == HIGH);


quote:

if(resetPin == LOW){
Serial.println("Reset button was pushed");
unsigned long bMills = millis(); //Assign the time the button was pushed to the current time.
delay(150); //Bounce back protection? So it only gets pressed "once"?
relayP.on(); //Open the relays
relayS.on();
while(millis() <= (bMills + 5000)){ //We add 5000 to the time the button was pushed.
digitalWrite(pBadStatus, HIGH); //This code then runs those 5000 milli seconds are up.
digitalWrite(sBadStatus, HIGH); //With the delays in here it will run longer than 5000 ms, but thats fine.
delay(500); //The blinking lights will indicate something is happening.
digitalWrite(pGoodStatus, LOW); //Its a fun visual feedback for the controllers.
digitalWrite(sGoodStatus, LOW); //They like blinking lights.
delay(500);
}
relayP.off(); //Once the 5000ms has passed, close the relays.
relayS.off();
timer_count = 0; //Reset timer after manual JB3 reset.
}//End of reset button = pushed

How does this look?

For the rest of my code I'm still using delays after the opening of the relays.

Foxfire_ posted:

Does this device need to do anything besides be a watchdog?

No, the only thing this device does is act as a watchdog. It opens and closes the relays and makes indicator LEDs change colors.
This is why I think the delays are fine; it doesn't need to be doing anything while they're open. In fact, I honestly don't want it to do anything else.

For context: This is a watchdog for two Air Traffic Information Systems. The controllers record their hourly ATIS on these two JB3s, which then play the recording on a loop. Specifically, the JB3 has an audio output pair (Audio+ & Audio-) and a keying output (Key+ & Key-). Our ATC radios are set up for grounding keying. AKA the radios transmit when the key line is shorted to ground. The keying relay stays closed for the duration of the message, opens as it is unkeyed for a few seconds, and then closes again for the next transmission.

The JB3s are hot garbage and go into a lockout state that can only be fixed by a power cycle. Thankfully, I noticed that when it is in that state the JB3s keying relay opens (1s duration) and closes (1 second duration) over and over until we power cycle it.
I have the watchdog hooked up to this keying relay, and it watches the relay open and close.
There is a value which counts up as the keying relay is open (unkeyed), and a value which counts up when they keying relay is closed (keyed). When the relay transitions from one state to another, its opposite value is reset to 0.

quote:

while(timer_count <= timeLimit){
pKeyState = digitalRead(pInputPin);
sKeyState = digitalRead(sInputPin);
if(pKeyState == HIGH){ //Remember, HIGH means UNKEYED!
jbP_Good = false;
p_Unkey_Count++;
p_work_count = 0;
Serial.println("Primary Not Keyed!");
} else {
jbP_Good = true;
p_Unkey_Count = 0;
p_work_count++;
pPrevWork++;
Serial.println("Primary Keyed");
}


That is, when the relay opens, the value for Unkeyed begins rising and Keyed goes to 0. When the relay closes, Unkeyed value goes to 0 and keyed starts counting.
I have a timer value that begins at 0, increments by one for each monitoring loop, and when it reaches timerLimit [While(timeValue >= timerLimit)] the watchdog judges the values of the Keyed and Unkeyed variables and decides if the radio is being Overkeyed (constant xmit; never seen it do that but seems prudent to test for), Underkeyed (JB3 frozen, common), or is fine.

If there is an issue it throws the power relay, and resets the timer value, and then begins testing again. If nothing is wrong, it resets the timer value and keeps monitoring (obviously). There is a third value that increments each cycle the radio is keyed, without being reset down to zero when the radio unkeys. I'm using this this ensure that there the watchdog doesn't accidently decide there is an underkey condition just because the JB3 happened to naturally unkey at the moment of evaluation.

quote:

while(timer_count >= timeLimit){
//Test for primary JB3 being unkeyed for too long
if(p_Unkey_Count >= underKeyLimit && p_work_count <= underKeyLimit && pPrevWork <= dCheckLimit) {
Serial.println("Something's wrong (UNDERKey)! Throwing Primary Relay!");
digitalWrite(pBadStatus, HIGH);
digitalWrite(pGoodStatus, LOW);
relayP.on(); //Relay ON I.E. COM->NO I.E. power disconnect.
delay(relayOpenTime);
relayP.off(); //Relay OFF I.E. COM->NC I.E. power reconnect.
Serial.println("Done.");
p_Unkey_Count = 0; //Reset the failure count. If you don't reset it it will fail forever. That is bad.
pResetCount++; //Increment the amount of times the primary has reset itself by one.
if(pResetCount >= resetLimit){
digitalWrite(alarmPin, HIGH);
break;
}
}//End of underkeytest for Primary.

That is the main function of this watchdog, but it should also have a push button for the ATC controllers to manually reset the JB3. Also there are LEDs for status indication, which, if this works correctly shouldn't really matter, but the controllers like the LEDs and it isn't too much more work to add some in there. Finally, there is a resetCount that increases each time the power relays are thrown, and is set back to 0 if it gets through a testing cycle without having an issue. If it resets three times in a row without working once, it kicks an alarm in our maintenance shop on and BREAK; the code to indicate there is something else wrong with the thing and we need to manually check it out.

Edit: All the Serial.println lines are for testing purposes. They'll most likely be commented out in final usage. Although the Arduino I'm using (actually an Open Source PLC) has a built in LED so I feel like I might as well set that up to display some of these values.

I should say, I am not a great coder. I never ever code, my career field is NOT trained in this in the slightest, and this is all ad-hoc. Hence the newbie questions.

Wrr fucked around with this message at 17:03 on Jan 13, 2022

Sockser
Jun 28, 2007

This world only remembers the results!




Sound_man posted:

I'm looking for a two pole connector for a project. Low amps, 3.3V signal but I'd prefer something a little more rugged than JST I'd like something a little smaller and cheaper than an XLR connector but I haven't come across anything I like. I'd need two mating sets so anything that requires custom tooling is also out.

Anyone have a clever lead?

XT30 connector?

Sound_man
Aug 25, 2004
Rocking to the 80s

Sockser posted:

XT30 connector?

Sold, 50 cents a pair shipped to my door. Bonus points for being solder. Thanks!

Sockser
Jun 28, 2007

This world only remembers the results!




Sound_man posted:

Sold, 50 cents a pair shipped to my door. Bonus points for being solder. Thanks!

Fwiw, soldering small-gauge wires to XT connectors kinda sucks and you end up just kind of pooling solder into them, at least IME

ickna
May 19, 2004

it's also worth the time to heat shrink over the individual wires + cups, and then the whole assembly afterwards as well for strain relief.

Foxfire_
Nov 8, 2010


I would approach this by dividing it into two big parts:
1) Loop until it's time for a reset
2) Do the reset, then go back to (1)

(1) would do:
- Have a loop that runs at some fixed interval, lets say every 10ms. Each iteration we need to:
* Decide if we want to reset because of the button:
- Debounce it since it's a physical button
- You probably don't want to keep resetting when you hold the button down, so exit when it goes pushed->released
* Decide if we want to reset because of the watchdog:
- Count how long it's been since the watchdog input changed
- Exit when the count gets big

Example: https://pastebin.com/wZ6gjvRM

Foxfire_ fucked around with this message at 06:25 on Jan 14, 2022

Enos Shenk
Nov 3, 2011


Sockser posted:

Fwiw, soldering small-gauge wires to XT connectors kinda sucks and you end up just kind of pooling solder into them, at least IME

I do a lot of RC, and planes and cars use a lot of XT series. They're very easy to melt the connector trying to solder, the best tip I found was plug the connectors into each other so at least you have a larger heat mass.

My dumb clock project is absolutely cursed. I broke down and ordered some bog standard 28BYJ-48 stepper motors. I drew up adapter blocks to mount them to the clock in place of the NEMA17's so I wouldn't have to rebuild everything. I had to make some axle extensions as well, but it all went together easily enough. The CNC shield wouldn't run them, but the good old Adafruit motor shield would. And loving finally, things started to turn. I got excited and started writing code to advance the hands to a reset position, and the hour hand stopped working.

Turns out the motors got stupid hot, and likely failed at the 3D printed axle extension, I haven't disassembled everything yet to find out but the motor just spins. So I'll have to try yet another power supply and rebuild the axles.



A shot of the rear of the thing, the interrupter shafts up top are geared to the clock arbor. Of course now that I changed motors the gear ratios are hosed, but I can fix that in code.

Wrr
Aug 8, 2010


Well I think I blew up that open-source PLC from digital-loggers. Good riddance. gently caress that thing. Even called the company trying to ask some basic questions about it and they said look at their website. I said I was looking and their website and the schematics and whatnot, and that I had questions about those. No joy. Also why are the digital outputs putting out +13 vdc? Maybe its too powerful for my tiny brain to comprehend. Whatever.

Bought a few relay shields and am just going to build my own setup. Going to try to take out the While()s from my loops and see if that makes the pushbutton, and overReset conditionals work.

I'm also using a reed relay now, an old w171dip-2. I know the alarm is hooked up normally through it as I keep closing the relay when my magnetized fingers get too close. But when I send +5 through the +5 input of the coil, with the other end of the coil connected to ground, I can hear it a make a tiny clinking noise but nothing happens. Trying to look more into that and find out if its not enough power or something to it

Wrr fucked around with this message at 15:09 on Jan 19, 2022

DC to Daylight
Feb 13, 2012

Wrr posted:

Well I think I blew up that open-source PLC from digital-loggers. Good riddance. gently caress that thing. Even called the company trying to ask some basic questions about it and they said look at their website. I said I was looking and their website and the schematics and whatnot, and that I had questions about those. No joy. Also why are the digital outputs putting out +13 vdc? Maybe its too powerful for my tiny brain to comprehend. Whatever.

Bought a few relay shields and am just going to build my own setup. Going to try to take out the While()s from my loops and see if that makes the pushbutton, and overReset conditionals work.

I'm also using a reed relay now, an old w171dip-2. I know the alarm is hooked up normally through it as I keep closing the relay when my magnetized fingers get too close. But when I send +5 through the +5 input of the coil, with the other end of the coil connected to ground, I can hear it a make a tiny clinking noise but nothing happens. Trying to look more into that and find out if its not enough power or something to it

For putting stuff together quickly and cheaply, I've had excellent luck with the little relay modules you can buy on amazon or whatever:

https://smile.amazon.com/Valefod-1-...C84&sr=8-2&th=1

There is a relay with suitable support circuitry to drive directly from a digital out (transistor, resistors, diode to snub the flyback when the coil opens). Also, low quality but usable screw terminals. And less than $2/ea.

Wrr
Aug 8, 2010


DC to Daylight posted:

For putting stuff together quickly and cheaply, I've had excellent luck with the little relay modules you can buy on amazon or whatever:

https://smile.amazon.com/Valefod-1-...C84&sr=8-2&th=1

There is a relay with suitable support circuitry to drive directly from a digital out (transistor, resistors, diode to snub the flyback when the coil opens). Also, low quality but usable screw terminals. And less than $2/ea.

I got three of these bad boys and a prototyping shield to slap them in. https://www.adafruit.com/product/3191

I was looking at some other things on Amazon, but I frankly don't trust them so went for sparkfun and adafruit's stock

DC to Daylight
Feb 13, 2012

Wrr posted:

I got three of these bad boys and a prototyping shield to slap them in. https://www.adafruit.com/product/3191

I was looking at some other things on Amazon, but I frankly don't trust them so went for sparkfun and adafruit's stock

That should do it with a little more class.

I can't speak for all of the 3d party hardware on Amazon, but the dollar fifty relays performed admirably when I did the first prototype for my heater controller. On the other hand, both of the "16-bit" A to D's I bought were fraudulently labelled 12 bit chips. I went with Adafruit because their board at least used the real IC.

Wrr
Aug 8, 2010


DC to Daylight posted:

That should do it with a little more class.

I can't speak for all of the 3d party hardware on Amazon, but the dollar fifty relays performed admirably when I did the first prototype for my heater controller. On the other hand, both of the "16-bit" A to D's I bought were fraudulently labelled 12 bit chips. I went with Adafruit because their board at least used the real IC.

I'm hand building all this for our ATC tower, and then transferring to another base in February. The people that will be left with this stuff have 0 experience with this sort of thing, so I don't want to risk having shoddy parts on something I built for them. Gotta keep my reputation nice and pretty, can't leave them with a lemon.

shame on an IGA
Apr 8, 2005

Wrr posted:

Well I think I blew up that open-source PLC from digital-loggers. Good riddance. gently caress that thing. Even called the company trying to ask some basic questions about it and they said look at their website. I said I was looking and their website and the schematics and whatnot, and that I had questions about those. No joy. Also why are the digital outputs putting out +13 vdc? Maybe its too powerful for my tiny brain to comprehend. Whatever.

Bought a few relay shields and am just going to build my own setup. Going to try to take out the While()s from my loops and see if that makes the pushbutton, and overReset conditionals work.

I'm also using a reed relay now, an old w171dip-2. I know the alarm is hooked up normally through it as I keep closing the relay when my magnetized fingers get too close. But when I send +5 through the +5 input of the coil, with the other end of the coil connected to ground, I can hear it a make a tiny clinking noise but nothing happens. Trying to look more into that and find out if its not enough power or something to it

it's not enough power, are you running straight off the digital out pin? spec sheet for that relay says they draw up to 290mw and that's only a nominal rating so it's quite possible yours exceeds that. I'd suggest using optocouplers.

Wrr
Aug 8, 2010


shame on an IGA posted:

it's not enough power, are you running straight off the digital out pin? spec sheet for that relay says they draw up to 290mw and that's only a nominal rating so it's quite possible yours exceeds that. I'd suggest using optocouplers.

Yeah, right off the arduino's digital out pin. I pulled this off of some old alarm panel someone built in, I dunno, the 2000s. I think it had a small 6 volt power supply connected to it and was activated by some UPS closing a relay at some other sites. The joys of just rummaging around work to find parts to slap together. The little alarm buzzer I have (from that same UPS alarm panel) gets a voltage on one pin and buzzes when then connected to ground. Using +5 VDC so that as well. Do you think if I had a pin that is normally high go low to count as connecting to ground?

Wrr
Aug 8, 2010


Wow simple things sometimes seem to be the hardest huh?

gently caress anything complicated; I just hooked the ground side of the buzzer up and can just logic HIGH the power side on and off as needed. Fuckin duh.

Foxfire_
Nov 8, 2010

Trying to drive an inductive load from a mcu pin with no other circuitry is fairly likely to destroy things even if you had enough drive. It will generate tens to hundreds of volts when you try to switch it off. Add a flyback diode

Ethics_Gradient
May 5, 2015

Common misconception that; that fun is relaxing. If it is, you're not doing it right.
Posted this in the general electronics thread, forgetting we have an Arduino thread!

I am a total beginner, working on an Arduino-based timer for my darkroom. I have this:

https://learn.adafruit.com/adafruit-led-backpack/1-2-inch-7-segment-backpack-arduino-wiring-and-setup

Which I soldered up yesterday (hopefully OK) and connected to a Nano via a breadboard.

I loaded the sketch onto my Nano from the Adafruit library but I only get a brief flicker (in the middle) on the LED display when I first connect the USB power. I've tried jiggling and applying a little bit of pressure at all the different connections just in case, and don't see any changes.

Anything super obvious I might be missing in the code? Not saying I'm confident in my soldering, but I'm even less confident in my ability to parse what's in the sketch :v: It seems like there are a few things included, not sure if I'm supposed to comment stuff to disable it so the other bits will work, or what.

code:
/*************************************************** 
  This is a library for our I2C LED Backpacks

  Designed specifically to work with the Adafruit LED 7-Segment backpacks 
  ----> http://www.adafruit.com/products/881
  ----> http://www.adafruit.com/products/880
  ----> http://www.adafruit.com/products/879
  ----> http://www.adafruit.com/products/878

  These displays use I2C to communicate, 2 pins are required to 
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

Adafruit_7segment matrix = Adafruit_7segment();

void setup() {
#ifndef __AVR_ATtiny85__
  Serial.begin(9600);
  Serial.println("7 Segment Backpack Test");
#endif
  matrix.begin(0x70);
}

void loop() {
  // try to print a number thats too long
  matrix.print(10000, DEC);
  matrix.writeDisplay();
  delay(500);

  // print a hex number
  matrix.print(0xBEEF, HEX);
  matrix.writeDisplay();
  delay(500);

  // print a floating point 
  matrix.print(12.34);
  matrix.writeDisplay();
  delay(500);

  // print a string message
  matrix.print("7SEG");
  matrix.writeDisplay();
  delay(10000);
  
  // print with print/println
  for (uint16_t counter = 0; counter < 9999; counter++) {
    matrix.println(counter);
    matrix.writeDisplay();
    delay(10);
  }

  // method #2 - draw each digit
  uint16_t blinkcounter = 0;
  boolean drawDots = false;
  for (uint16_t counter = 0; counter < 9999; counter ++) {
    matrix.writeDigitNum(0, (counter / 1000), drawDots);
    matrix.writeDigitNum(1, (counter / 100) % 10, drawDots);
    matrix.drawColon(drawDots);
    matrix.writeDigitNum(3, (counter / 10) % 10, drawDots);
    matrix.writeDigitNum(4, counter % 10, drawDots);
   
    blinkcounter+=50;
    if (blinkcounter < 500) {
      drawDots = false;
    } else if (blinkcounter < 1000) {
      drawDots = true;
    } else {
      blinkcounter = 0;
    }
    matrix.writeDisplay();
    delay(10);
  }
}

VelociBacon posted:

Do you have a proper ground in the circuit? This reminds me of when I was starting and didn't have the ground hooked up properly.

You can find free arduino learning tools online where you can put your code in and build your circuit in a flash player or something and you can 'turn it on' and see what happens. If it doesn't work in the webapp then you have some code or circuit issue. If it works in the webapp you've got a bad connection somewhere IRL.

I'm pretty sure it's grounded correctly; black wire goes to the GND pin on the Arduino. It's plugged into my computer via a USB hub (did try it powered directly off a wall wart in case the hub wasn't providing enough voltage, but no change).

I was initially trying that but I think the backpack is going to be too specialised to appear in any of the libraries of doodads. Very happy to be wrong though!

Ethics_Gradient fucked around with this message at 23:12 on Apr 16, 2022

Adbot
ADBOT LOVES YOU

babyeatingpsychopath
Oct 28, 2000
Forum Veteran


Ethics_Gradient posted:

Which I soldered up yesterday (hopefully OK) and connected to a Nano via a breadboard.

I loaded the sketch onto my Nano from the Adafruit library but I only get a brief flicker (in the middle) on the LED display when I first connect the USB power. I've tried jiggling and applying a little bit of pressure at all the different connections just in case, and don't see any changes.

Anything super obvious I might be missing in the code? Not saying I'm confident in my soldering, but I'm even less confident in my ability to parse what's in the sketch :v: It seems like there are a few things included, not sure if I'm supposed to comment stuff to disable it so the other bits will work, or what.


I'm pretty sure it's grounded correctly; black wire goes to the GND pin on the Arduino. It's plugged into my computer via a USB hub (did try it powered directly off a wall wart in case the hub wasn't providing enough voltage, but no change).

I was initially trying that but I think the backpack is going to be too specialised to appear in any of the libraries of doodads. Very happy to be wrong though!

Let's see the soldering job. Since it's I2C, there's a chance your soldering may have bridged/broken the I2C address pins so your code isn't trying to talk to the right device. The brief flicker at power-on may or may not be good. The I2C LED stuff I have doesn't do ANYTHING until it sees valid I2C instructions on the bus, so the flickering may indicate that something's cross-wired.

Can you still talk to the Nano via the serial port monitor while your code is running?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply