Need some help with incrementing, waiting for an input, then decrementing...

Hi!
I’m trying to recreate an Edison’s cradle (刈谷康時 Yasutoki Kariya - Asobi | 武蔵野美術大学 Musashino Art University - YouTube) and I need some help with coding…

I need the LEDs to light up in one direction, activate a solenoid, wait for a push on the same solenoid, then light up in the other direction and do the same with the other solenoid.

I’m working with a shift register (HC595) and my code is below. I can get the LEDs to light up in one direction, but not in the other. Also, as I have never worked with a solenoid and don’t have one handy right now, I’d love some help with the coding for that too.

/*

https://programmingelectronics.com/tutorial-12-for-loop-iteration/
https://www.arduino.cc/reference/en/language/structure/control-structure/for/
https://www.arduino.cc/reference/en/language/structure/compound-operators/increment/

*/

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
byte LEDs = 0;

void setup()
{
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}

void loop()
{
LEDs = 0;
updateShiftRegister();
delay(50);
for (int i = 0; i < 8; i++)
{
bitSet(LEDs, i);
updateShiftRegister();
delay(50);
}
}

void updateShiftRegister()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, LEDs);
digitalWrite(latchPin, HIGH);
}

Thanks in advance!

Edison_s_Cradle_-_Anu.ino (1007 Bytes)

AnuragKS:
I need the LEDs to light up in one direction, activate a solenoid, wait for a push on the same solenoid,

Are you sure "solenoid" is the correct word?

Solenoids are electromagnet devices that cause a push (or pull) when their coil is energized. Your description suggests that you have a momentary switch that something pushes against.

...R

Where is your attempt to light the LEDs up in the other direction? You just need another loop that starts with 7 and ends with 0, decrementing the index by one in the loop.

What kind of input does the solenoid need? Do you just need to turn the solenoid on, or do you need to PWM it? How IS it connected to the Arduino? There should be a motor controller or circuit between it and the Arduino, since the Arduino almost certainly can not provide the required current.

 for (int i = 0; i < 8; i++)

What do you think might happen if the for loop counted from 7 to 0 instead of 0 to 7 ?

wait for a push on the same solenoid,

You don’t normally push solenoids

Add Serial.begin() to your setup() and print the values you are sending to the shift register like this:

    bitSet(LEDs, i);
    Serial.println(LEDs, BIN);

You should see the same pattern over and over in the serial monitor, this explains why the LEDs keep lighting in the same pattern.

The bits should be turned on in opposite directions in each pass of loop(). Writing out the bit operations instead of using bitSet() might seem more complicated at first but if you trace through the code I think it looks obvious what is going on.

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
byte LEDs = 0;

bool rightToLeft = true;    // true => bits are moving from LSB to MSB

void setup()
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);

}

void loop()
{
  LEDs = 0;
  updateShiftRegister();
  delay(50);
  for (int i = 0; i < 8; i++)
  {
    // turn on next bit to the right or left
    LEDs |= (rightToLeft) ? 1 << i : 0b10000000>>i;
    Serial.println(LEDs, BIN);
    updateShiftRegister();
    delay(50);
  }

  // flip direction
  rightToLeft = !rightToLeft;

}

void updateShiftRegister()
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, LEDs);
  digitalWrite(latchPin, HIGH);
}

Robin2:
Are you sure "solenoid" is the correct word?

Solenoids are electromagnet devices that cause a push (or pull) when their coil is energized. Your description suggests that you have a momentary switch that something pushes against.

...R

I'm pretty sure I'm gonna use a push-solenoid. Is there a way to "read" the solenoid being pushed back after it pushes the bulb on the end, or will i just have to time it?

UKHeliBob:

 for (int i = 0; i < 8; i++)

What do you think might happen if the for loop counted from 7 to 0 instead of 0 to 7 ?
You don’t normally push solenoids

I tried decrementing the count, but I might not have coded properly. I’ll try again in the morning, but I’m unsure about the code. Also, I may have been unclear - the solenoid I’m talking about is a push-solenoid, and me referring to “pushing the solenoid back in” is the bulb pushing the solenoid back to it’s starting place, or back into the case - the opposite direction to the initial push. I don’t know if reading that push back is possible, which means that I may have to time it though…

I suppose that you could sense the change in solenoid current or voltage, but usually there is no reading a solenoid.

Perhaps an optical sensor?

I tried this, but all I saw in the serial monitor was a different pattern repeating in the same direction. This was mirrored in the LEDs too, instead of the LEDs turning off after they light up a=for a certain amount of time, they stayed on. Then, they turned off in the same direction. I wanted the LEDs to switch on for a certain amount of time, switch off immediately, and move to the next one. Once the light reaches the last LED, it “bounces” back and the above loop repeats in the other direction.

I didn’t get the part about turning bits off as the code moves along based on your original code. As for the delay, you have specified 50 milliseconds, which is a really short amount of time. You really should try to trace through the code with paper and pencil to see what’s going on.

Making a small change to the bit setting and adding a print binary function to show leading zeros:

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
byte LEDs = 0;

bool rightToLeft = true;    // true => bits are moving from LSB to MSB

void setup()
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);

}

void loop()
{
  LEDs = 0;
  updateShiftRegister();
  delay(50);
  for (int i = 0; i < 8; i++)
  {
    // turn on next bit to the right or left
    LEDs = 0 | (rightToLeft) ? 1 << i : 0b10000000>>i;
    printBin(LEDs);
    updateShiftRegister();
    delay(500);
  }

  // flip direction
  rightToLeft = !rightToLeft;

}

void printBin(byte b)
{
  byte mask = 0b10000000;
  for(int i=0; i < 8; i++)
  {
    Serial.print(b&mask ? 1 : 0);
    mask = mask>>1;
  }
  Serial.println();
}

void updateShiftRegister()
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, LEDs);
  digitalWrite(latchPin, HIGH);
}

I see this in the serial monitor:

00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000
10000000
01000000
00100000
00010000
00001000
00000100
00000010
00000001
00000001

Which I think is what you want. Those repeating values at either end of the pattern might bother you but it should be close.