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
Aurium
Oct 10, 2010

neogeo0823 posted:

Ok, so I found an Instructables thing on how to get analog feedback output from my servos. How do I integrate that into my code in any meaningful way?

First off you'd need to figure out how the output of the analog feedback relates to the position.

Lets assume that your 0-720 degree range maps to 152-872 coming off the adc (it won't). This range is (1024-720)/2 (analog read max-the number of degrees you have / 2 to give it equal buffer size)

I also assume you've found the right math to feed servo.write the range of 0-720. this should be a simple map function of from something like 0-720 to 45-135 ( or whatever your subset of the 0-180 range of the servo ends up being) I'm calling this corrected_servo(degrees) and will just feed it a value of 0-720.

Really rough code :

so it'd go

code:
void corrected_servo(degrees)
{
	//45 and 135 are experimentally derived to your hardware
	servo.write(map(degrees, 0, 720, 45, 135))
}


//give it a 0-720 and have it move fast
void fast_servo_move(int degrees)
{
	//get current position
	int current_position = analogread(feedback_pin)

	mapped_degrees = map(degrees, 0, 720, 152, 872 )

	//this is affected by the 152-872 range
	if(mapped_degrees > current position)
	{
		//move to full positive if requested position is greater than current position

		//note that it may be faster still if you used servo.write(180)
		//written like this it would still be slow if you're close to the end.
		//where as you'd never actually be at the actual extremes of the servo
		//which would always give you best speed.
		//if you understand why this is, I'd use servo.write(180) here.		

		corrected_servo(720);
	}
	else
	{	
		//full negative if  requested position is less than current position

		//note that it may be faster still if you used servo.write(0)

		corrected_servo(0);
	}

	//wait to get within 15 degrees
	while( abs(mapped_degrees  - current_position) > 15)
	{
		delay(10)	
		current_position = analogread(feedback_pin)
	}

	//it's close, so set the servo to the desired value
	corrected_servo(degrees)
}
Once you get the appropriate ranges, I encourage you can ask for help again. Note that if you're supplying your servo with 6v the voltage of your analog feedback pot may fall outside the safe voltage range of your arduino. If you're powering it with 5v you won't have a problem. (unless you're using a 3.3v arduino)

Adbot
ADBOT LOVES YOU

PDP-1
Oct 12, 2004

It's a beautiful day in the neighborhood.
I've never actually tried doing this, but it seems like it'd be possible to 'overdrive' the servo a bit during long moves by adding your own proportional control in code. Something like this:

code:
int SV;      // our setpoint variable, aka where we want to go
int PV;      // our process variable, aka where the servo actually is
int SV2;     // our 'overdrive' setpoint variable
int upperBound, lowerBound;  // the upper and lower bounds of the range we want the servo to move through
float P;   // a proportional control term that we'll have to experiment to find the right value for

while(1)
{
     PV = readActualServoPositionHere();
     SV2 = SV + (int)(P * (SV - PV));                       
     if(SV2>upperBound){ SV = upperbound; }
     if(SV2<lowerBound){ SV = lowerBound; }
     writeNewServoDriveValueHere(SV2);  
}
Just to game out how that would work, suppose our proportional constant P is 1.0f, we are starting at 0% rotation and want to go to 50% rotation. On the first iteration of the loop the overdriven setpoint is SV2 = 50% + 1.0f * (50% - 0%) or SV2=100%. This means that we're telling the servo that it's way off the mark and it should move really fast.

Now suppose the servo has turned for a bit and is at 45% rotation. The new overdriven setpoint is SV2 = 50% + 1.0f * (50% - 45%) or SV2 = 55%. In other words, as the servo approaches its final position the overdrive variable starts to slack off a bit. It's easy to see that when SV=PV, aka we're exactly where we want to be, SV2=SV so the overdrive isn't doing anything anymore.

Basically we're adding our own proportional control loop term to the servo's internal control loop to speed it up when it's far from the desired position. To find the appropriate value for P run the servo under normal load conditions and gradually increase P until the servo starts to oscillate around the setpoint position. Throttle P back to about 70% of the minimum P value that causes oscillations.

mobby_6kl
Aug 9, 2009

by Fluffdaddy
Just ordered an ATMEGA328-based Arduino-complatible mystery board off banggood for exactly 3 bucks with shipping. Supposedly they work fine so I'm curious if it'll do what little I expect from it.

rawrr
Jul 28, 2007
I bought like 3 of the Arduino Nano clones (I like that you can just plug them directly onto the breadboard, and the smaller size is also easier to integrate into projects), and they've all worked fine. I recently picked up like 6 more for $12 shipped just to have some extras.

There are also smaller Digispark/Adafruit Trinket clones based on the ATTINY, but they're only like 50 cents cheaper.

With these sort of suspiciously cheap things I tend to prefer to use aliexpress or dhgate, because they allow users to leave listing specific reviews and sort by review ratings or items sold, making it less of a crapshoot, though I haven't had problems with ones I ordered on eBay.

TVarmy
Sep 11, 2011

like food and water, my posting has no intrinsic value

I've had good luck with insanely cheap ebay electronic components. I imagine there's probably knockoffs, counterfeits, and bad labeling, but for hobbyist purposes they're a great deal.

If you look up prices for AVR chips, they're insanely cheap in bulk, and Arduino designs are fairly simple and open source, so cheap clones make sense. The biggest problem is probably just bad build quality. But if you're getting a board for sub-$5 when you'd normally pay $20 for an official board with the same design, it's hard to complain.

But I learned the hard way that you shouldn't buy the cheapest Taiwanese breadboard. The stiff springs are a major pain and ruin components and jumper wires that don't have a thin pin at the end.

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES
Okay, working on the project again tonight, curious if this is something that will work (besides the part where I need help fixing error "'leds_value' was not declared in this scope
'leds_value' was not declared in this scope")

code:
//Libraries
#include "FastLED.h"
//Setting up the MSGEQ7 processor
int analogPin = 0; // MSGEQ7 OUT
int strobePin = 2; // MSGEQ7 STROBE
int resetPin = 4; // MSGEQ7 RESET
int spectrumValue[7];
int filterValue = 80;
//# of LEDs in Strip
#define NUM_LEDS 392
//Data Pin Output
#define DATA_PIN 6
// This is an array of leds.  One item for each led in your strip.
CRGB leds[NUM_LEDS];
// This function sets up the LEDs and tells the controller about them as well as setting up the processor
void setup() {
  Serial.begin(9600);
  pinMode(analogPin, INPUT);
  pinMode(strobePin, OUTPUT);
  pinMode(resetPin, OUTPUT);
  analogReference(DEFAULT);
  digitalWrite(resetPin, LOW);
  digitalWrite(strobePin, HIGH);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}

void loop()
{
  // Set reset pin low to enable strobe
  digitalWrite(resetPin, HIGH);
  digitalWrite(resetPin, LOW);

  // Get all 7 spectrum values from the MSGEQ7
  for (int i = 0; i < 7; i++)
  {
    digitalWrite(strobePin, LOW);
    delayMicroseconds(30); // Allow output to settle

    spectrumValue[i] = analogRead(analogPin);

    // Constrain any value above 1023 or below filterValue
    spectrumValue[i] = constrain(spectrumValue[i], filterValue, 1023);

    // Remap the value to a number between 0 and 255
    spectrumValue[i] = map(spectrumValue[i], filterValue, 1023, 0, 255);
    Serial.print(spectrumValue[i]);
    Serial.print(" ");
    digitalWrite(strobePin, HIGH);
  }
  Serial.println();
  // The actual displaying of the LEDs
  for (int i = 0; i < NUM_LEDS / 2 - 1 < 154; i++) {
    //this line is to get rid of background noise, change it higher if there is more noise
    if (spectrumValue[i % 7] > 50) {
      //and this is the line that controls LED colors as well as determining how bright
      leds_value = CHSV((i / 11) * 32, 255, spectrumValue[i / 11]);
      leds[i] = leds_value;
      leds[NUM_LEDS - i] = leds_value;
    }
    for (int i = 154; i < NUM_LEDS / 2 - 1 < 238; i++) {
      //this line is to get rid of background noise, change it higher if there is more noise
      if (spectrumValue[i % 7] > 50) {
        //and this is the line that controls LED colors as well as determining how bright
        leds_value = CHSV((i / 6) * 32, 255, spectrumValue[i / 6]);
        leds[i] = leds_value;
        leds[NUM_LEDS - i] = leds_value;
      }
      for (int i = 238; i < NUM_LEDS / 2 - 1 < 392; i++) {
        //this line is to get rid of background noise, change it higher if there is more noise
        if (spectrumValue[i % 7] > 50) {
          //and this is the line that controls LED colors as well as determining how bright
          leds_value = CHSV((i / 11) * 32, 255, spectrumValue[i / 11]);
          leds[i] = leds_value;
          leds[NUM_LEDS - i] = leds_value;
        }
        //And to fade them out gently if no further input
        leds[i].fadeToBlackBy(8);
      }
      FastLED.show();
    }

Data Graham
Dec 28, 2009

📈📊🍪😋



Pretty sure it's telling you the truth about leds_value not being declared in that (or any) scope

TVarmy
Sep 11, 2011

like food and water, my posting has no intrinsic value

Yeah, you just need to add "int leds_value;" up above void setup().

Captain Cool
Oct 23, 2004

This is a song about messin' with people who've been messin' with you

dirtycajun posted:

code:
  for (int i = 0; i < NUM_LEDS / 2 - 1 < 154; i++)

    for (int i = 154; i < NUM_LEDS / 2 - 1 < 238; i++)

      for (int i = 238; i < NUM_LEDS / 2 - 1 < 392; i++)
These lines are not going to do what you want. You want one loop from 0 to 76, one from 154 to one ninety something, and one from 238 to 320 or so. Inside those loops you need to change the last assignment from NUM_LEDS-i to something that covers the gaps (77-153, 19x-237, 32x-392).

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES
Okay before I address that part I am still getting an error:

error: cannot convert 'CHSV' to 'int' in assignment

NM, Captain Cool figured it out. Back to the assigning of the strands.

dirtycajun fucked around with this message at 02:47 on Oct 7, 2015

Parts Kit
Jun 9, 2006

durr
i have a hole in my head
durr
I think you might have an extra bracket in the end, or be lacking one earlier in the program. Towards the end there's a } I can't find the { for.

Also none of those for loops are nested right? Seems like a bad idea to the same int variable for a bunch of different loops though I guess you could get away with it as long as they aren't nested.

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES
So working on it like this then:

code:
//Libraries
#include "FastLED.h"
int analogPin = 0; // MSGEQ7 OUT
int strobePin = 2; // MSGEQ7 STROBE
int resetPin = 4; // MSGEQ7 RESET
int spectrumValue[7];
int filterValue = 80;
#define NUM_LEDS 392
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
CRGB leds_value;
void setup() {
  Serial.begin(9600);
  pinMode(analogPin, INPUT);
  pinMode(strobePin, OUTPUT);
  pinMode(resetPin, OUTPUT);
  analogReference(DEFAULT);
  digitalWrite(resetPin, LOW);
  digitalWrite(strobePin, HIGH);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}

void loop()
{
  digitalWrite(resetPin, HIGH);
  digitalWrite(resetPin, LOW);

  for (int i = 0; i < 7; i++)
  {
    digitalWrite(strobePin, LOW);
    delayMicroseconds(30); // Allow output to settle

    spectrumValue[i] = analogRead(analogPin);

    spectrumValue[i] = constrain(spectrumValue[i], filterValue, 1023);

    spectrumValue[i] = map(spectrumValue[i], filterValue, 1023, 0, 255);
    Serial.print(spectrumValue[i]);
    Serial.print(" ");
    digitalWrite(strobePin, HIGH);
  }
  Serial.println();
  // LEDs 1-154
  for (int i = 0; i < (NUM_LEDS - 238) / 2 - 1; i++) {
    if (spectrumValue[i % 7] > 50) {
      leds_value = CHSV((i / 11) * 32, 255, spectrumValue[i / 11]);
      leds[i] = leds_value;
      leds[NUM_LEDS - i - 238] = leds_value;
    }
    leds[i].fadeToBlackBy(8);
  }
  // LEDs 155-238
  for (int i = 154; i < NUM_LEDS / 2 - 1; i++) {
    if (spectrumValue[i % 7] > 50) {
      leds_value = CHSV((i / 6) * 32, 255, spectrumValue[i / 6]);
      leds[i] = leds_value;
      leds[NUM_LEDS - i] = leds_value;
    }
    leds[i].fadeToBlackBy(8);
  }
  // LEDs 239-392
  for (int i = 238; i < (NUM_LEDS + 238) / 2 - 1; i++) {
    if (spectrumValue[i % 7] > 50) {
      leds_value = CHSV((i / 11) * 32, 255, spectrumValue[i / 11]);
      leds[i] = leds_value;
      leds[NUM_LEDS - i + 238] = leds_value;
    }
    leds[i].fadeToBlackBy(8);
  }
  FastLED.show();
}
Do I need to have the " leds[i].fadeToBlackBy(8);" in there three times or can I just run it once at the end?

Captain Cool
Oct 23, 2004

This is a song about messin' with people who've been messin' with you

dirtycajun posted:

So working on it like this then:
Looks okay. Does it work? I get nervous when I see things like "i+238" in an array index, but I think the math works out in this case.

quote:

Do I need to have the " leds[i].fadeToBlackBy(8);" in there three times or can I just run it once at the end?
You need to run it on each LED, right? Then you'll also need to call it with leds[NUM_LEDS-i...].

rawrr
Jul 28, 2007
What's the easiest (and reasonably pin efficient) way to drive, say, three single digit 7 segment displays? Will I need a separate driver (i.e. MAX7219) for each digit? It seems like the four digit, 7 segment displays can be driven by just one driver.

e: I guess this is what I should be looking at?


from: http://playground.arduino.cc/Main/MAX72XXHardware

Is using the MAX7219 driver pretty much the best way to drive 7 segment displays?

rawrr fucked around with this message at 20:55 on Oct 7, 2015

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES
Okay, so the final question in the three part marathon of questions:

I set this up simply using only one MSGEQ7 in the code so far, but in reality it uses two of them in a Left Right RCA input. One stand will display LEDs for the instruments on the right including the theremin and the other the instruments on the left. The theremin stand will display the average of the two inputs.

At what point do I add something along the lines of "(spectrumValueRight + spectrumValueLeft) / 2 = spectrumValueMid" and is that how I would go about averaging those two values so that I have an average on the middle stand?

code:
//Libraries
#include "FastLED.h"
int analogPinR = 0; // MSGEQ7 Right OUT
int analogPinL = 1; // MSGEQ7 Left OUT
int strobePinR = 2; // MSGEQ7 Right STROBE
int strobePinL = 3; // MSGEQ7 Left STROBE
int resetPinR = 4; // MSGEQ7 Right RESET
int resetPinL = 5; // MSGEQ7 Left Reset
int spectrumValueRight[7];
int spectrumValueLeft[7];
int spectrumValueMid[7];
int filterValue = 80;
#define NUM_LEDS 392
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
CRGB leds_value;
void setup() {
  Serial.begin(9600);
  pinMode(analogPinR, INPUT);
  pinMode(analogPinL, INPUT);
  pinMode(strobePinR, OUTPUT);
  pinMode(strobePinL, OUTPUT);
  pinMode(resetPinR, OUTPUT);
  pinMode(resetPinL, OUTPUT);
  analogReference(DEFAULT);
  digitalWrite(resetPinR, LOW);
  digitalWrite(resetPinL, LOW);
  digitalWrite(strobePinR, HIGH);
  digitalWrite(strobePinL, HIGH);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}

void loop()
{
  digitalWrite(resetPinR, HIGH);
  digitalWrite(resetPinL, HIGH);
  digitalWrite(resetPinR, LOW);
  digitalWrite(resetPinL, LOW);

  for (int i = 0; i < 7; i++)
  {
    digitalWrite(strobePinR, LOW);
    digitalWrite(strobePinL, LOW);
    delayMicroseconds(30); // Allow output to settle

    spectrumValueRight[i] = analogRead(analogPinR);
    spectrumValueLeft[i] = analogRead(analogPinL);

    spectrumValueRight[i] = constrain(spectrumValueRight[i], filterValue, 1023);
    spectrumValueLeft[i] = constrain(spectrumValueLeft[i], filterValue, 1023);

    spectrumValueRight[i] = map(spectrumValueRight[i], filterValue, 1023, 0, 255);
    spectrumValueLeft[i] = map(spectrumValueLeft[i], filterValue, 1023, 0, 255);
    Serial.print(spectrumValueRight[i]);
    Serial.print(spectrumValueLeft[i]);
    Serial.print(" ");
    digitalWrite(strobePinR, HIGH);
    digitalWrite(strobePinL, HIGH);
  }
  Serial.println();
  // LEDs 1-154
  for (int i = 0; i < (NUM_LEDS - 238) / 2 - 1; i++) {
    if (spectrumValueRight[i % 7] > 50) {
      leds_value = CHSV((i / 11) * 32, 255, spectrumValueRight[i / 11]);
      leds[i] = leds_value;
      leds[NUM_LEDS - i - 238] = leds_value;
    }
    leds[i].fadeToBlackBy(8);
    leds[NUM_LEDS - i - 238].fadeToBlackBy(8);
  }
  // LEDs 155-238
  for (int i = 154; i < NUM_LEDS / 2 - 1; i++) {
    if (spectrumValueMid[i % 7] > 50) {
      leds_value = CHSV((i / 6) * 32, 255, spectrumValueMid[i / 6]);
      leds[i] = leds_value;
      leds[NUM_LEDS - i] = leds_value;
    }
    leds[i].fadeToBlackBy(8);
    leds[NUM_LEDS - i].fadeToBlackBy(8);
  }
  // LEDs 239-392
  for (int i = 238; i < (NUM_LEDS + 238) / 2 - 1; i++) {
    if (spectrumValueLeft[i % 7] > 50) {
      leds_value = CHSV((i / 11) * 32, 255, spectrumValueLeft[i / 11]);
      leds[i] = leds_value;
      leds[NUM_LEDS - i + 238] = leds_value;
    }
    leds[i].fadeToBlackBy(8);
    leds[NUM_LEDS - i + 238].fadeToBlackBy(8);
  }
  FastLED.show();
}

dirtycajun fucked around with this message at 04:31 on Oct 8, 2015

Captain Cool
Oct 23, 2004

This is a song about messin' with people who've been messin' with you

rawrr posted:

What's the easiest (and reasonably pin efficient) way to drive, say, three single digit 7 segment displays? Will I need a separate driver (i.e. MAX7219) for each digit? It seems like the four digit, 7 segment displays can be driven by just one driver.
I haven't pulled up any chip datasheets, but here's someone who was doing the same thing recently: http://forums.somethingawful.com/showthread.php?threadid=2734977&userid=124396#post447466792

dirtycajun posted:

Okay, so the final question in the three part marathon of questions:

I set this up simply using only one MSGEQ7 in the code so far, but in reality it uses two of them in a Left Right RCA input. One stand will display LEDs for the instruments on the right including the theremin and the other the instruments on the left. The theremin stand will display the average of the two inputs.

At what point do I add something along the lines of "(spectrumValueRight + spectrumValueLeft) / 2 = spectrumValueMid" and is that how I would go about averaging those two values so that I have an average on the middle stand?
Right after you get the final values for left and right:

quote:

code:
    spectrumValueRight[i] = map(spectrumValueRight[i], filterValue, 1023, 0, 255);
    spectrumValueLeft[i] = map(spectrumValueLeft[i], filterValue, 1023, 0, 255);

neogeo0823
Jul 4, 2007

NO THAT'S NOT ME!!

What's the easiest way to have something trigger(for the sake of example, let's say it's having a Pin go high) when a button is released?

peepsalot
Apr 24, 2007

        PEEP THIS...
           BITCH!

neogeo0823 posted:

What's the easiest way to have something trigger(for the sake of example, let's say it's having a Pin go high) when a button is released?
Use the internal pullup on the pin and tie the switch to ground, assuming it's normally open.
https://www.arduino.cc/en/Tutorial/DigitalPins

mod sassinator
Dec 13, 2006
I came here to Kick Ass and Chew Bubblegum,
and I'm All out of Ass
And in the code constantly read the input pin for the button and look for a low -> high level transition. That only occurs the exact moment the button is released (when the button is pressed the input is pulled down to ground, then when released the pull-up will pull it back up to a high level). If you test for that transition from low to high then you'll easily catch the button being released. Do something like:
code:
// Take two readings for the button input, add a small delay to catch the low to high transition.
bool first = digitalRead(BUTTON_PIN);
delay(10);
bool second = digitalRead(BUTTON_PIN);
// Check if the first is low and the second is high, that means the button was released.
if (!first && second) {
  // Button was released!  Do stuff here.
}
// Be careful in the rest of your loop not to spend too much time or else the two reading check above might miss the low -> high transition.

Data Graham
Dec 28, 2009

📈📊🍪😋



That seems risky and finicky. Just keep a state variable and set it on every iteration through the loop, but before you set it check the current value against the previous loop's value and see if it's different. No need for delays that way.

But then you want to think about debouncing: https://www.arduino.cc/en/Tutorial/Debounce

TheresaJayne
Jul 1, 2011
I have been having problems with a sketch i have been working on, I don't know yet whether it is bad wiring (using a breadboard) or bad logic in the sketch

The plan was to have a trigger so closing the lid of a box would trigger the servo to move to the lock position.

Then even though the lock button is pressed, when the unlock button / reed sensor is triggered it will unlock the servo for 30 seconds before resetting and if the lid is still closed relock the box.

But it locks and will not unlock until i release the lock button which is not the functionality i need.

code:

Servo servo;

boolean locker;
int servoPos;
int pinRead;
void setup()
{
  locker = false;
  pinMode(1,INPUT);
  pinMode(2,INPUT);
  servo.attach(9);
  servoPos = 0;
  servo.write(servoPos); //Set to unlock position
}

void loop()
{
  if(locker == false)
  {
    pinRead = digitalRead(1);
    if (pinRead == HIGH)
    {
      servoPos = 180;
      locker = true;
      servo.write(servoPos);                                    
    }
  }
  else
  {
    pinRead = digitalRead(2);
    if(pinRead == HIGH)
    {
      servoPos = 0;
        servo.write(servoPos);
      delay(20000);
    }
  }
}

Deanut Pancer
Nov 24, 2012
Looks like you're missing a "locker = false;" assignment just after the "delay(20000);" statement?

TheresaJayne
Jul 1, 2011

Deanut Pancer posted:

Looks like you're missing a "locker = false;" assignment just after the "delay(20000);" statement?

Actually my plan currently is to get it working where you have to reset to get it to relock,
The problem is that button 2 never works if button 1 is down

Combat Pretzel
Jun 23, 2004

No, seriously... what kurds?!
A friend of mine asked me, whether I can implement some coin counter, that counts coins per session, total and an average per hour. I figured I'll get an Arduino starter kit (and tinker with it). Question is, the IR sender and receiver in these kits, they're essentially just a LED and a photodiode that I can just go use as a lightbarrier instead, right?

Parts Kit
Jun 9, 2006

durr
i have a hole in my head
durr
I don't think so, I think those are more like the stuff in a tv remote control? But there are optical switches that would do that at a low cost. If you go for optical switches be sure to read the specs carefully as they come with different channel widths and heights, and some of them are not going to be useful for something as 'fat' as a coin.

Another easy option would be a microswitch without a roller on the lever. A coin going down a chute should have more than enough force to click it and keep moving out of the way so it resets. Might put more of a limit how fast you can run coins in though.

Captain Cool
Oct 23, 2004

This is a song about messin' with people who've been messin' with you

TheresaJayne posted:

Actually my plan currently is to get it working where you have to reset to get it to relock,
The problem is that button 2 never works if button 1 is down
How are your buttons connected? Also, if you want some action to happen after the 20 second delay, you need some code there. Otherwise, as written, the delay doesn't matter because the loop can't do anything after that point.

Combat Pretzel posted:

A friend of mine asked me, whether I can implement some coin counter, that counts coins per session, total and an average per hour. I figured I'll get an Arduino starter kit (and tinker with it). Question is, the IR sender and receiver in these kits, they're essentially just a LED and a photodiode that I can just go use as a lightbarrier instead, right?
Do you really need to implement your own sensor? If this is for an arcade machine or something you should be able to tap into the "coin inserted" signal that's already present.

Subyng
May 4, 2013
Can someone recommend me a retailer where I can buy misc mechanical parts like gears and such? Either online or if you're in the Greater Toronto Area, a physical store? Hobby shops seem to only have parts that are part of kits. At this point I'm thinking it might be easier to just buy some Lego technic pieces and adapt them to my servo.

Speaking of which, I'm trying to build a very simple "finger" which really just needs to be a rigid bar that rotates. The problem is I need to have the axis of rotation of the finger 90 degrees to the output shaft of my servo (I can't just rotate the entire motor). I'm thinking of just using 2 bevel gears 90 degrees apart, one on the servo shaft and the other in the finger. Is there an easier way to do this from a mechanical perspective or just in terms of acquiring the necessary parts?

Combat Pretzel
Jun 23, 2004

No, seriously... what kurds?!

Captain Cool posted:

Do you really need to implement your own sensor? If this is for an arcade machine or something you should be able to tap into the "coin inserted" signal that's already present.
Lazy person scenario. He's in some carnival society and they're frequently hosting parties. Drinks are a voucher or plastic coin each, and these are bought at the entrance. Sounds stupid, but when the beer price is 1.30€, it's easier to sell plastic coins in bulk than fiddle with change all the time. They've been throwing the coins into a bucket and count them the day after. He wants to know the count and optional ancillary stats (beer per hour) immediately, thus a custom coin counter with a light barrier.

I suppose a regular LED and photodiode should cut it, too, when enclosed and sufficiently shielded from external light sources? I'd need to calibrate the Schmitt trigger I want to use on the analog input first, anyway (I've already seen basic schematics for an Arduino counter with a lightbarrier).

Bad Munki
Nov 4, 2008

We're all mad here.


Subyng posted:

Can someone recommend me a retailer where I can buy misc mechanical parts like gears and such? Either online or if you're in the Greater Toronto Area, a physical store? Hobby shops seem to only have parts that are part of kits. At this point I'm thinking it might be easier to just buy some Lego technic pieces and adapt them to my servo.

Lots of the robotics supply places sell bits 'n pieces, but, like, All Hail McMaster-Carr (it sounds like you probably want the "power transmission" section)

Data Graham
Dec 28, 2009

📈📊🍪😋



TheresaJayne posted:

Actually my plan currently is to get it working where you have to reset to get it to relock,
The problem is that button 2 never works if button 1 is down

Honestly you really shouldn't be using delay(large_number) in anything except the simplest and most trivial code. You're basically freezing the execution of the code for 20 seconds, and that blocks all other processing. Maybe that's fine in a case this simple but I'd recommend doing a timer approach:

code:

unsigned long triggertime = 0;

void loop {
    if (millis() - triggertime > 20000) {
        do whatever
        triggertime = millis();
    }
    do other things
}

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES
So I have built the beast and implemented the code, unfortunately it looks like my serial monitor is going nuts with zero input from my end and it's doing all kinds of crazy poo poo with the LEDs, but only the first strand (might be a construction error) Any idea on what's going on?

code:
//Libraries
#include "FastLED.h"
int analogPinR = 0; // MSGEQ7 Right OUT
int analogPinL = 1; // MSGEQ7 Left OUT
int strobePinR = 2; // MSGEQ7 Right STROBE
int strobePinL = 3; // MSGEQ7 Left STROBE
int resetPinR = 4; // MSGEQ7 Right RESET
int resetPinL = 5; // MSGEQ7 Left Reset
int spectrumValueRight[7];
int spectrumValueLeft[7];
int spectrumValueMid[7];
int filterValue = 80;
#define NUM_LEDS 392
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
CRGB leds_value;
void setup() {
  Serial.begin(9600);
  pinMode(analogPinR, INPUT);
  pinMode(analogPinL, INPUT);
  pinMode(strobePinR, OUTPUT);
  pinMode(strobePinL, OUTPUT);
  pinMode(resetPinR, OUTPUT);
  pinMode(resetPinL, OUTPUT);
  analogReference(DEFAULT);
  digitalWrite(resetPinR, LOW);
  digitalWrite(resetPinL, LOW);
  digitalWrite(strobePinR, HIGH);
  digitalWrite(strobePinL, HIGH);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}
 
void loop()
{
  digitalWrite(resetPinR, HIGH);
  digitalWrite(resetPinL, HIGH);
  digitalWrite(resetPinR, LOW);
  digitalWrite(resetPinL, LOW);
 
  for (int i = 0; i < 7; i++)
  {
    digitalWrite(strobePinR, LOW);
    digitalWrite(strobePinL, LOW);
    delayMicroseconds(30); // Allow output to settle
 
    spectrumValueRight[i] = analogRead(analogPinR);
    spectrumValueLeft[i] = analogRead(analogPinL);
 
    spectrumValueRight[i] = constrain(spectrumValueRight[i], filterValue, 1023);
    spectrumValueLeft[i] = constrain(spectrumValueLeft[i], filterValue, 1023);
 
    spectrumValueRight[i] = map(spectrumValueRight[i], filterValue, 1023, 0, 255);
    spectrumValueLeft[i] = map(spectrumValueLeft[i], filterValue, 1023, 0, 255);
    spectrumValueMid[i] = (spectrumValueRight[i] + spectrumValueLeft[i]) / 2;
    Serial.print(spectrumValueRight[i]);
    Serial.print(spectrumValueLeft[i]);
    Serial.print(" ");
    digitalWrite(strobePinR, HIGH);
    digitalWrite(strobePinL, HIGH);
  }
  Serial.println();
  // LEDs 1-154
  for (int i = 0; i < (NUM_LEDS - 238) / 2 - 1; i++) {
    leds_value = CHSV((i / 11) * 32, 255, spectrumValueRight[i / 11]);
    leds[i] = leds_value;
    leds[NUM_LEDS - i - 238] = leds_value;
    leds[i].fadeToBlackBy(8);
    leds[NUM_LEDS - i - 238].fadeToBlackBy(8);
  }
  // LEDs 155-238
  for (int i = 154; i < NUM_LEDS / 2 - 1; i++) {
    leds_value = CHSV((i / 6) * 32, 255, spectrumValueMid[i / 6]);
    leds[i] = leds_value;
    leds[NUM_LEDS - i] = leds_value;
    leds[i].fadeToBlackBy(8);
    leds[NUM_LEDS - i].fadeToBlackBy(8);
  }
  // LEDs 239-392
  for (int i = 238; i < (NUM_LEDS + 238) / 2 - 1; i++) {
    leds_value = CHSV((i / 11) * 32, 255, spectrumValueLeft[i / 11]);
    leds[i] = leds_value;
    leds[NUM_LEDS - i + 238] = leds_value;
    leds[i].fadeToBlackBy(8);
    leds[NUM_LEDS - i + 238].fadeToBlackBy(8);
  }
  FastLED.show();
}
from the serial monitor:
2020 1919 1818 1918 1818 1717 1817
1918 1818 1717 1817 1717 1716 1716
1818 1817 1716 1717 1716 1615 1616

ThinkFear
Sep 15, 2007

Combat Pretzel posted:

Lazy person scenario. He's in some carnival society and they're frequently hosting parties. Drinks are a voucher or plastic coin each, and these are bought at the entrance. Sounds stupid, but when the beer price is 1.30€, it's easier to sell plastic coins in bulk than fiddle with change all the time. They've been throwing the coins into a bucket and count them the day after. He wants to know the count and optional ancillary stats (beer per hour) immediately, thus a custom coin counter with a light barrier.

I suppose a regular LED and photodiode should cut it, too, when enclosed and sufficiently shielded from external light sources? I'd need to calibrate the Schmitt trigger I want to use on the analog input first, anyway (I've already seen basic schematics for an Arduino counter with a lightbarrier).

I know this is the arduino thread, but don't over complicate it. China grade panel mount counter and capacitive prox, done for under $20 and even fewer minutes.

Captain Cool
Oct 23, 2004

This is a song about messin' with people who've been messin' with you

dirtycajun posted:

So I have built the beast and implemented the code, unfortunately it looks like my serial monitor is going nuts with zero input from my end and it's doing all kinds of crazy poo poo with the LEDs, but only the first strand (might be a construction error) Any idea on what's going on?
Do the values on serial look right? You're expecting them to vary with sound, right? Do they?

To debug a physical error, comment out your three LED loops and replace them with a single loop that just sets all LEDs to an arbitrary value.

Combat Pretzel
Jun 23, 2004

No, seriously... what kurds?!

ThinkFear posted:

I know this is the arduino thread, but don't over complicate it. China grade panel mount counter and capacitive prox, done for under $20 and even fewer minutes.
Eh, it was mostly motivated by "I wanted to play with an Arduino anyway, and someone is paying for it, making it a zero sum game if I don't like it". :v:

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES

Captain Cool posted:

Do the values on serial look right? You're expecting them to vary with sound, right? Do they?

To debug a physical error, comment out your three LED loops and replace them with a single loop that just sets all LEDs to an arbitrary value.

No those are values that are occurring with no input.

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES
Small project till I finish work on the main one tomorrow and tuesday.

I built the drum lights gemma project for my roommate's kickdrum a bit ago but it's way too (basically any noise will set it off) sensitive. Looking at the code below how do I turn down the sensitivity.

EDIT: actually gently caress most of this. He just wants all the LEDs to shine for a half second and then turn off until summoned again. Please help me gut this code (mostly I need to know how to use the mic input better)

code:
/* LED "Color Organ" for Adafruit Trinket and NeoPixel LEDs.
 
Hardware requirements:
 - Adafruit Trinket or Gemma mini microcontroller (ATTiny85).
 - Adafruit Electret Microphone Amplifier (ID: 1063)
 - Several Neopixels, you can mix and match
   o Adafruit Flora RGB Smart Pixels (ID: 1260)
   o Adafruit NeoPixel Digital LED strip (ID: 1138)
   o Adafruit Neopixel Ring (ID: 1463)
 
Software requirements:
 - Adafruit NeoPixel library
 
Connections:
 - 5 V to mic amp +
 - GND to mic amp -
 - Analog pinto microphone output (configurable below)
 - Digital pin to LED data input (configurable below)
 
Written by Adafruit Industries.  Distributed under the BSD license.
This paragraph must be included in any redistribution.
*/
#include <Adafruit_NeoPixel.h>
 
#define N_PIXELS  60  // Number of pixels you are using
#define MIC_PIN    1  // Microphone is attached to Trinket GPIO #2/Gemma D2 (A1)
#define LED_PIN    0  // NeoPixel LED strand is connected to GPIO #0 / D0
#define DC_OFFSET  0  // DC offset in mic signal - if unusure, leave 0
#define NOISE     100  // Noise/hum/interference in mic signal
#define SAMPLES   60  // Length of buffer for dynamic level adjustment
#define TOP       (N_PIXELS +1) // Allow dot to go slightly off scale
// Comment out the next line if you do not want brightness control or have a Gemma
#define POT_PIN    3  // if defined, a potentiometer is on GPIO #3 (A3, Trinket only) 
 
byte
  peak      = 0,      // Used for falling dot
  dotCount  = 0,      // Frame counter for delaying dot-falling speed
  volCount  = 0;      // Frame counter for storing past volume data
  
int
  vol[SAMPLES],       // Collection of prior volume samples
  lvl       = 10,     // Current "dampened" audio level
  minLvlAvg = 0,      // For dynamic adjustment of graph low & high
  maxLvlAvg = 512;
 
Adafruit_NeoPixel  strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
 
void setup() {
  memset(vol, 0, sizeof(vol));
  strip.begin();
}
void loop() {
  uint8_t  i;
  uint16_t minLvl, maxLvl;
  int      n, height;
  n   = analogRead(MIC_PIN);                 // Raw reading from mic 
  n   = abs(n - 512 - DC_OFFSET);            // Center on zero
  n   = (n <= NOISE) ? 0 : (n - NOISE);      // Remove noise/hum
  lvl = ((lvl * 7) + n) >> 3;    // "Dampened" reading (else looks twitchy)
  
  // Calculate bar height based on dynamic min/max levels (fixed point):
  height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);
 
  if(height < 0L)       height = 0;      // Clip output
  else if(height > TOP) height = TOP;
  if(height > peak)     peak   = height; // Keep 'peak' dot at top
 
// if POT_PIN is defined, we have a potentiometer on GPIO #3 on a Trinket 
//    (Gemma doesn't have this pin)
  uint8_t bright = 255;   
#ifdef POT_PIN            
   bright = analogRead(POT_PIN);  // Read pin (0-255) (adjust potentiometer 
                                  //   to give 0 to Vcc volts
#endif
  strip.setBrightness(bright);    // Set LED brightness (if POT_PIN at top
                                  //  define commented out, will be full)
  // Color pixels based on rainbow gradient
  for(i=0; i<N_PIXELS; i++) {  
    if(i >= height)               
       strip.setPixelColor(i,   0,   0, 0);
    else 
       strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
    } 
 
   strip.show(); // Update strip
 
  vol[volCount] = n;                      // Save sample for dynamic leveling
  if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter
 
  // Get volume range of prior frames
  minLvl = maxLvl = vol[0];
  for(i=1; i<SAMPLES; i++) {
    if(vol[i] < minLvl)      minLvl = vol[i];
    else if(vol[i] > maxLvl) maxLvl = vol[i];
  }
  // minLvl and maxLvl indicate the volume range over prior frames, used
  // for vertically scaling the output graph (so it looks interesting
  // regardless of volume level).  If they're too close together though
  // (e.g. at very low volume levels) the graph becomes super coarse
  // and 'jumpy'...so keep some minimum distance between them (this
  // also lets the graph go to zero when no sound is playing):
  if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
  minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
  maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
}
 
// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

dirtycajun fucked around with this message at 23:15 on Oct 18, 2015

DreadLlama
Jul 15, 2005
Not just for breakfast anymore
edit: re-read op. Am dumb. Nevermind.

DreadLlama fucked around with this message at 05:00 on Oct 19, 2015

Captain Cool
Oct 23, 2004

This is a song about messin' with people who've been messin' with you

dirtycajun posted:

No those are values that are occurring with no input.
0 gets constrained to 80 which gets mapped to 20 which starts fading.

Actually, now that I look at it, your fade call isn't really going to do anything useful. You're using fresh values for all LEDs each time through. If you want them to fade out on no input, you need to detect the low input and not set those lights to any new value that time through the loop.

dirtycajun posted:

EDIT: actually gently caress most of this. He just wants all the LEDs to shine for a half second and then turn off until summoned again. Please help me gut this code (mostly I need to know how to use the mic input better)
If the mic read is high, turn on the lights and reset a timeout time to millis() + 500. If millis() passes the timeout time, turn the lights off.

dirtycajun
Aug 27, 2004

SUCKING DICKS AND SQUEEZING TITTIES

Captain Cool posted:

0 gets constrained to 80 which gets mapped to 20 which starts fading.

Actually, now that I look at it, your fade call isn't really going to do anything useful. You're using fresh values for all LEDs each time through. If you want them to fade out on no input, you need to detect the low input and not set those lights to any new value that time through the loop.

If the mic read is high, turn on the lights and reset a timeout time to millis() + 500. If millis() passes the timeout time, turn the lights off.

The map doing that makes a lot of sense thank you.

Adbot
ADBOT LOVES YOU

neogeo0823
Jul 4, 2007

NO THAT'S NOT ME!!

So, as I mentioned in a previous post, I'm using this multi-function button code as a base for my project. It's been working well so far. The code allows me to turn on multiple lights through various types of clicks and holds and execute code based on which lights are on or off. However, I recently got some RGB LEDs in, and now I'm a bit stuck. See, I want to replace the 3 LEDs I'm using with 1 RGB LED, which will fade between different colors to indicate which modes are activated. The problem is that all my extra code is currently written so that it executes based on which LED is currently on. What I need is some way to separate which click mode is active from which LEDs are on or off, so that I can execute code for each mode and also have the LEDs fading between colors.

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