Crank position doesn't update every frame?

SDK 2.5.0. I'm seeing this in Sim (Linux) but also on device. I'm wondering if I'm fundamentally misunderstanding something with the crank. It seems like the crank position doesn't update every frame, and this gets worse at high frame rates (>30 fps).

I'm trying to poll the crank each frame and determine the delta. I've tried using getCrankPosition() and getCrankChange() but see the same results. Sometimes, the delta is just zero between frames. Here's a simple example. These bars flicker wildly, because every 2-3 frames I get zero for the crank position change.

Is this normal?

playdate.display.setRefreshRate(50)

function playdate.update()
    playdate.graphics.clear()
    change, accel = playdate.getCrankChange()
    playdate.graphics.fillRect(200, 32, change, 16)
    playdate.graphics.fillRect(200, 64, accel, 16)
end```

Hi, both values will be 0 when you're not moving the crank. Change is a number representing how many degrees the crank has moved from the previous frame, so if it reports 0, it indicates that the crank has not moved. In contrast, getCrankPosition reports what position the crank is currently in. If you try it that way, you shouldn't see any flickering:

function playdate.update()
    playdate.graphics.clear()
    local position <const> = playdate.getCrankPosition()
    playdate.graphics.fillRect(200, 32, position, 16)
end
2 Likes

Hey, thanks for replying. Maybe I wasn't clear on the issue. I think this is a bug.

I'm trying to get a delta for the crank per frame.

I first tried getCrankChange(), but noticed that both variables returned from this function sometimes come back as zero, even though I'm moving the crank at a constant rate.

I then looked at getCrankPosition() to try and calculate my own delta, but noticed that it sometimes returns the same value as the previous frame, even though the crank is turning at a constant rate. I suspect this is why getCrankChange() returns zero sometimes.

I've reproduced this in SDK 2.5.0 on Linux sim with software crank, with a device as the controller, on hardware (both revs) and now I've reproduced it in Mac OS sim as well.

Do you move the crank by hand? I have tried the following example and moved the crank with the slider on the left side of the simulator's crank input, which results in constant rate, and there are no zeros reported on my side. On the other hand, when I move the crank manually, I can see some zeros there.

Screenshot 2024-06-04 at 23.16.11

playdate.display.setRefreshRate(50)

function playdate.update()
    playdate.graphics.clear()
    local change <const> = playdate.getCrankChange()
    print(change)
    playdate.graphics.drawRect(200, 115, change, 10)
end

In what scenario do you need the value?

Good idea about frame rate set to 50.

What frame rate is the problem game running at?
Do you see better or worse results at higher or lower frame rates?

I find moving the crank at a constant rate with the sim "dial" to be difficult, which is why I mentioned I'm using the device as a controller. It's pretty easy to rotate at a constant rate this way. Also, as I mentioned, this happens on hardware not just the sim.

At 50 fps, it's pretty easy to spot every 2-3 frames. At lower frame rates, you can still "catch" a zero frame occasionally, but it's much less common. I think this is just because the polling rate of the program is lower so you're more likely to miss one of these periods of time where the crank is not updating.

Here's a small program I've used to try to visualize this.

function playdate.update()
    -- "scroll" the screen
    local i = playdate.graphics.getDisplayImage()
    i:draw(-5, 0)
    
    -- get crank change since last frame
    change, accel = playdate.getCrankChange()

    -- Draw a bar for the new change
    playdate.graphics.setColor(playdate.graphics.kColorWhite)
    playdate.graphics.fillRect(394, 0, 5, 240)
    playdate.graphics.setColor(playdate.graphics.kColorBlack)
    playdate.graphics.fillRect(394, 120, 5, change)
    print(change)
end

I've given up on reading crank delta directly, as I can't seem to get to the bottom of this. I've taken to averaging out updates to smooth out the hitches where the crank position doesn't update for a frame or two. This mostly works, but introduces some unavoidable lag.

That's exactly how the system works (worked if there have been changes?)

I'll tag @dave for his opinion