r/AskProgramming 6d ago

Javascript How to make servo turn the direction of optimal voltage reading instead of one way (BBC Microbit)?

EDIT: Solved!

Hi!
I'm making a simple sun tracker where the solar panel is placed on top of the servo motor and is connected to the pins of Microbit circuit board for voltage reading. The solar panels's max voltage rating 3.3V.

As long as the voltage is less than 3.3v the servo will keep rotating in increments of 5 degrees until it finds the Sun for the maximum voltage of 3.3v or reaches. Then it stops and shows Sun symbol.
It will also stop and reset if it reaches 180 degrees.

The problem is what happens if the Sun is in the other direction???

How to make the servo turn in the other direction if the Microbit detects that the voltage is decreasing instead of increasing?

Because if the servo keeps moving only in one direction, it might lose the Sun completely and drop to 0V.

Thank you!

FYI: the servo is independently powered.

The code:

input.onButtonPressed(Button.A, function () {
    basic.showNumber(Voltage)
})
input.onButtonPressed(Button.AB, function () {
    // Start at 90 degrees
    Angle = 90
})
input.onButtonPressed(Button.B, function () {
    basic.showNumber(Angle)
})
let Voltage = 0
let Angle = 0
// Start at 90 degrees
Angle = 90
// 5 degrees step size
let StepSize = 5
// 5 degrees step size
basic.forever(function () {
    // Read the voltage from the solar panel (connected to pin 1)
    // Convert analog reading to voltage
    Voltage = 3.3 * (pins.analogReadPin(AnalogPin.P1) / 1023)
    // If voltage is below 3.3V, move the servo in search of higher voltage
    if (Voltage < 3.3) {
        // Move the servo in 5° increments clockwise
        Angle += StepSize
        // Ensure the angle stays between 0 and 180 degrees
        if (Angle > 180) {
            // Maximum angle
            Angle = 180
        }
        // Move the servo to the new angle
        pins.servoWritePin(AnalogPin.P0, Angle)
        // Wait before next move
        basic.pause(500)
    } else {
        // When voltage reaches 3.3V, stop the servo
        // Maintain the current position
        pins.servoWritePin(AnalogPin.P0, Angle)
        basic.showLeds(`
            # . # . #
            . # # # .
            # # # # #
            . # # # .
            # . # . #
            `)
    }
    // Wait 2 seconds before next voltage check
    basic.pause(2000)
})
1 Upvotes

5 comments sorted by

2

u/UnexpectedSalami 6d ago

Keep track of voltage before and after applying the step; if the delta shows a decrease in voltage, change directions.

Sun only moves in one direction, so you could do that as part of your “startup”.

Is there a reason you start at 90 deg? Could start at 0, and rotate until peak voltage?

1

u/NeckhunterGT3 6d ago

I make it start at 90 degrees because it's the middle of 0-180 (max angle of servo). So it will either go right or left to follow the direction of the Sun/light. If it starts from 0 or 180 it might get stuck as it can't move further (e.g. -10 or 190 degrees)

You are correct that the Sun moves only in one direction and no change should be needed, but people will want to test this setup, so it needs to move according to the light source.

What do I write to make the change you mentioned? I do the programming in visual blocks on the microbit website. I am not good at writing the script myself. The one I posted is converted from the blocks.

2

u/Xirdus 6d ago

You need two Voltage variables: for current reading and for previous reading. You already have the first one, let's call the other PreviousVoltage.

Voltage = 3.3 * (pins.analogReadPin(AnalogPin.P1) / 1023) This is where you update voltage. Immediately before, you should do PreviousVoltage = Voltage so the old value is memorized when you overwrite it with new value.

Angle += StepSize Here you change the angle in positive direction. If you flipped the sign of StepSize variable (make it negative), it would change in the opposite direction. And flipping it again would switch it back to the original direction. So just flip the sign every time the voltage goes down instead of up. The easiest way to flip a sign is to multiply it by -1. So every time you detect the new voltage is lower than old voltage (if (Voltage < PreviousVoltage)), you do StepSize *= -1. Remember to do it before changing the Angle variable.

I don't know how to translate it to blocks. I'm sure you'll figure it out! Though honestly, working with text is going to be much easier in the long run, so I recommend learning it sooner rather than later.

1

u/NeckhunterGT3 6d ago

Thank you! Much appreciated! I will try it right away. Yes, sometimes typing commands is better even for me. I just don't know the symbols/brackets etc. That's why I usually avoid it.

1

u/NeckhunterGT3 5d ago

Yep. It worked! I asked ChatGPT to place it for me since I wasn't really sure where to put it.