Looks like this is going to be one of my longform forum posts again ;) Challenge accepted.
It wasn’t until recently that I saw visualizations of a Sine Wave that I fully understood what makes them tick. This was the image (ignore the bottom two, entrancing though they may be :D ):
I wont try to explain the mathematics, because my experience with using sin
in code is almost entirely the result of trial and error. Let’s just get into the bare facts as they apply to programming:

math.sin
returns a value between 1 and +1

math.sin
expects an input value in radians = 180 degrees = PI radians
 the difference in radians between an output value of 1 and +1 is PI
The easy way to see this is like to go to our repl and try it out:
import math
>>> math.sin(math.pi*0.5)
1.0
>>> math.sin(math.pi*1.5)
1.0
If we feed sin
an incremental number, either via a variable, or time.time()
then it will oscillate between 1
and 1
.
You can go back to the Python repl and see this like so:
import math
import time
while True:
print(math.sin(time.time()))
This will also give you some feel for how quickly it changes. Want it to change faster? Simply multiply time.time()
, slower? Simply divide time.time()
.
The result of math.sin(time.time() * SPEED)
is therefore a number which goes from 1
to 1
over a duration of time which we control.
The next challenge is to scale that 1 to 1
range to the width of the matrix. Including hidden pixels Microdot pHAT is 45 pixels wide ( 56 for the matrix themselves, and 35 for the 5 spaces of 3 pixels each between them ).
First, let’s get out 1 to 1
to be 0 to 1
:
>>> (1 + 1) / 2
0
>>> (1 + 1) / 2
1
Adding 1 gives us 0 to 2
, and dividing by 2 gives us 0 to 1
Now to get a number between 0 and 44 ( because the first pixel is at index 0 ) we just multiply the result by 44 and round it to a whole number, since there’s no such thing as half a pixel!
This leaves us with something like this:
speed = 1.0
delta = time.time()
scale = math.sin(delta * speed)
offset_y = round(44 * scale)
And that’s the y
position for your scanning bar.
Your delta doesn’t have to be time.time()
, it could be a number that you increment or some other external factor.