lancaster-university / codal-microbit-v2

CODAL target for the micro:bit v2.x series of devices
MIT License
43 stars 52 forks source link

Erratic output when reading multiple analog pins #81

Closed komodo108 closed 3 years ago

komodo108 commented 3 years ago

Attached is the source & compiled binaries for a minimum C++ & Makecode example demonstrating the issue.

To demonstrate the issue, P0 should be connected to +3.3V while P1 should be connected to ground. Expected output would be a stream of ~0. However, in both programs we can observe regular erratic jumps in output to ~1024.

In my testing I have found that:

martinwork commented 3 years ago

After removing the timer/sample trigger, wait for STATUS to show not busy before calling STOP. I noticed that adding some DMESGFs fixed it, and thought waiting on the busy flag might make sense, but it feels more like a bug than a feature. If this isn't the real cause, I'm pretty sure it can be made to work by adding some pauses at appropriate places.

I've just stopped the test after about 4hrs. So, fingers crossed, the remaining issue is an occasional dud initial value for a channel changing from digital to analogue.

finneyj commented 3 years ago

great - that sounds good! Let me know when you have a PR ready. I'm looking forward to getting this one fixed!

martinwork commented 3 years ago

@finneyj https://github.com/lancaster-university/codal-nrf52/pull/26

martinwork commented 3 years ago

@finneyj Please see https://infocenter.nordicsemi.com/topic/errata_nRF52833_Rev1/ERR/nRF52833/Rev1/latest/anomaly_833_212.html and https://github.com/martinwork/codal-nrf52/commit/93e8133629d4c484b036daf8023e7fa96db8bd9f

With this change the bad initial values after a stop/start have gone. Could there be any downside?

It says "the SAADC configuration is reset. Before use all registers must be configured again.", so I have added setGain() to the channel configuration, but that would reset any changes to the gain. If we have to use this fix, should we add gain and bias member variables to the channel, and create a configureGain() function?

finneyj commented 3 years ago

Thanks @martinwork.

My word that's some black magic incantations going on there! The addresses being accessed are undocumented and mostly just after the end of the other ADC registers... It's interesting that Nordic obviously have some undocumented back door hardware APIs!

Yes, I think we should maintain state for the per channel gain and bias if we're adopting this approach (which if it works I'm in favour of!). Adding/removing channels can happen dynamically, and should be as transparent as possible to code using the other channels.

martinwork commented 3 years ago

@finneyj PR https://github.com/lancaster-university/codal-nrf52/pull/27

finneyj commented 3 years ago

Thanks @martinwork - just merged this in.

It's starting to feel like we're at the point where we could do with some external testing now, especially to make sure the streaming APIs still work ok.

@JoshuaAHill - Do you think you could run some of your input pipeline changes against this branch to make sure everything still works ok with sound input? Maybe stream some audio to file and see if the quality is OK in audacity etc?

https://github.com/lancaster-university/codal-nrf52/tree/adc-live-demux

martinwork commented 3 years ago

@finneyj Should the black magic be made conditional somehow, as it's possibly nRF52833 specific?

martinwork commented 3 years ago

@finneyj Please see PR https://github.com/lancaster-university/codal-nrf52/pull/29

I lost the fact that setGain used to configure the SAADC. I don't know if it needs to cycle the adc. Previously it used the NRF52_ADC_CHANNEL_STATUS_CONFIG_CHANGED flag.

finneyj commented 3 years ago

Thanks @martinwork. This could affect some issues around the gain that @JoshuaAHill has been seeing on the microphone...

I don't think that we need to cycle the ADC to change the per channel gain settings... as it doesn't affect the MUX ordering or anything.

I guess it's not a very common operation, but could cause a bit of churn as setGain() is commonly used soon after getting a new channel to configure it... So then we'd commonly restart the ADC twice each time we get a channel?

I think I'd prefer it to just poke the values into the SAADC rather than restart (if it works). What do you think?

martinwork commented 3 years ago

@finneyj OK, I'll make a new PR.

martinwork commented 3 years ago

@finneyj PR https://github.com/lancaster-university/codal-nrf52/pull/30

finneyj commented 3 years ago

Looks good - thanks!

I'll merge in now. @JoshuaAHill - After I've merged, can you confirm here if this fixes the problem with the microphone gain?

martinwork commented 3 years ago

@finneyj I'm not sure if it's an issue, because I don't fully understand how this works, but I noticed that NRF52_ADC_CHANNEL_STATUS_CONNECTED is only ever set. There's no method that clears that flag, and disconnecting the output's downstream doesn't inform the upstream.

finneyj commented 3 years ago

Thanks @martinwork. My, you're on a roll today!

I think NRF52ADC predates an update to the CODAL streams API, where we started to allow dynamic connection/disconnection of components. Strictly not a problem, but implementing disconnect() "would be nice" . :)

microbit-carlos commented 3 years ago

@martinwork @finneyj is this resolved and can be closed?

finneyj commented 3 years ago

I believe so @microbit-carlos.

@JoshuaAHill could you please confirm that you haven't seen any untoward behaviour during your work on the audio input pipeline?

martinwork commented 3 years ago

I haven't hit any problems with it @microbit-carlos

JoshuaAHill commented 3 years ago

Updated my branches and done some quick tests, all still looks good my end - values still as expected :)

finneyj commented 3 years ago

cool - thanks @JoshuaAHill. I think we're good to close this off then.

Thanks for all the work on this issue @komodo108 @martinwork @JoshuaAHill @microbit-carlos