Reading Multiplexed Analogue Inputs
-
Hi!
I'm using a Sammy C21 board to read 16 analogue inputs from a CD74HC4067 multiplexer board and write the values into an array using daemon.g.
P10-P13 control which of the multiplexers inputs is connected to the analogue input of the Sammy C21 (pa04).Multiplexer Setup:
;setup mux control outputs M950 P10 C"124.pa20" Q65535 ;S0 M950 P11 C"124.pa21" Q65535 ;S1 M950 P12 C"124.pa24" Q65535 ;S2 M950 P13 C"124.pa25" Q65535 ;S3 ;setup mux analogue input M308 S2 P"124.pa04" Y"linear-analog" A"Mux Analogue Input" F0
My daemon.g file:
; daemon.g global.muxValues = vector(16,null) while(true) M42 P10 S0 ;mux input select 0 M42 P11 S0 ;mux input select 1 M42 P12 S0 ;mux input select 2 M42 P13 S0 ;mux input select 3 G4 P600 while(iterations < #global.muxValues) var inputNumber = iterations while(var.inputNumber>0) if(mod(var.inputNumber,2)==1) M42 P{10+iterations} S1 set var.inputNumber = var.inputNumber - 1 else M42 P{10+iterations} S0 set var.inputNumber = var.inputNumber/2 G4 P600 set global.muxValues[iterations] = sensors.analog[2].lastReading
I've found through trial and error that a 600ms pause (G4 P600) is required between setting the multiplexer selector pins and reading the analogue input for reliable operation. It's working but is a bit slower than I was hoping for. I've found that reducing the delay causes the same analogue read value to be written to multiple entries in the global.muxValues array.
So my questions are:
-
I read somewhere that duet firmware only updates the sensor.analog[X] value in the object model every ~250ms. Is this correct and is there a way that I can increase the frequency of the updates? Or is there a command that can be sent to force the analogue input to be read?
-
When the digital output pins are set using M42 PXX SX etc. how long does it take for the output to actually change? Does this command block until the output has actually changed? My thinking here was that the delay was possibly required because the digital outputs were slow to change and the analogue value was being read before the selector pins to the multiplexer had changed state.
-
Is there anything else obvious that might be causing the slow updates of the analogue inputs and what could the fix be if any?
Apologies for the lengthy post. The firmware and the meta GCode capability is absolutely fantastic!
Thank you in advance.
-
-
@rotocopier to answer the specific questions we will need @dc42 's input however I note you are using this within daemon.g
have you tested it outside of daemon.g, at least initially, and how is the performance there?
-
- You are correct, analog sensors are read and the object model updated every 250ms. The exception is an analog Z probe; the value is updated every time you request it.
There is also a small latency in the value read. The analog inputs that are in use are read in a cycle, with each input being read multiple times and the values averaged to get a more accurate result. This latency is small, of the order of a millisecond or perhaps a few milliseconds.
- M42 commands that are intermixed with G1 or other movement commands from the same input channel are put into a queue and RRF waits for all the previous movement commands to complete before executing the M42, so that it gets executed at the proper time in the input command sequence. So if you have e.g. a G1 command followed by a M42 command followed by a command to read an input, the command to read the input is likely to take place before the M42 command.
M42 commands received from an input channel that does not command motion are executed more or less immediately. They may be delayed a little if writing to the SD card takes place, for example because logging is enabled. However, the following command will not be executed until the M42 command has been executed.
HTH David
-
Thank you both for your responses.
@dc42 this has helped me out enormously. I think you're right on the money with:@dc42 said in Reading Multiplexed Analogue Inputs:
a G1 command followed by a M42 command followed by a command to read an input, the command to read the input is likely to take place before the M42 command.
I went back and tested a few things and found the above to be true. The solution I came up with was to set the mux select pins with M42 in daemon.g and then idle in a while loop until they had changed according to the object model:
while((state.gpOut[10].pwm!=var.muxInputs[0])&&(state.gpOut[11].pwm!=var.muxInputs[1])&&(state.gpOut[12].pwm!=var.muxInputs[2])&&(state.gpOut[13].pwm!=var.muxInputs[1])) continue G4 P250 set global.muxValues[iterations] = sensors.analog[2].lastReading
I found that a 250ms delay was still required to get consistent results, but this is much better than the 600ms I had before.
I also tried using an M400 after setting the mux pins, but unsurprisingly, this caused to print to stutter as the move queue emptied and refilled again.Thanks again for all your help. Keep up the good work!
-
-