Conflicting SPI/stdlib libraries

Okay we’re getting closer. The logs definitely capture the input data that lead to the program outputting

[RX] ff for TX 40
[RX] 83 for TX aa
[RX] ff for TX 40
[RX] 6 for TX aa
[RX] 0 for TX 42
[RX] 0 for TX aa
[RX] 0 for TX aa
[RX] 0 for TX aa
[RX] 0 for TX 50
[RX] 90 for TX aa
[RX] ce for TX aa
[TX] 10
[TX] 10
[TX] ce

test
P1channel (Type 84)
	_ADC CJ code = 16777215
	R_rtd = 1600.00 ohmi
	cj_Temp = 157.17
	cj_Voltage = 7.07 mV
	_ADC TC code = 0
	th_Voltage_read = -78.12 mV
	th_Voltage = -71.06 mV

So the magic 16777215 number is still there. I just need to some time to see how the program process the incoming SPI data to compute _ADC JC and see if it’s “justified” coming up with that number based on the received SPI data.

One thing for sure is that the incoming SPI data is not all 0xFF so it’s definitely working to some degree.

A common problem with porting Uno code to Due code is that on an Uno, the int datatype is 16-bit, but on a Due it’s 32-bit. In certain datatype conversions that can bite very badly.

1 Like

I see, what is your method of checking to see if the _ADC JC value is being calculated correctly? Apologies for my many questions, I very much do enjoy learning from these threads. I usually have fruitful learning experiences here which I appreciate!

Great thanks for the traces. I’ve gone ahead and used mocking techniques to compile the sketch for x64 Desktop and feed it the received SPI from the log when it asks for that. Now I have a program.exe that outputs the same data as the Due did.

RTD channel calibration completed!
TC channel calibration completed!
test
P1channel (Type T)
	_ADC CJ code = 16777215
	R_rtd = 1600.00 ohmi
	cj_Temp = 157.17
	cj_Voltage = 7.07 mV
	_ADC TC code = 0
	th_Voltage_read = -78.12 mV
	th_Voltage = -71.06 mV

	WARNING: Linearized temperature value is not available -> exceeds lower limit!!!
		 Supported temperature range for thermocouple Type T [-200400
]

And the 16777215 bug is also visible there.

Now it’s a matter of seeing whether it’s justified to spit out that number based on the received SPI data or whether there’s a sneaky data conversion error somewhere.

Thankfully, stepping through the code is really is now that it’s running natively on desktop, as the PIO debugger can be used, breakpoints can be set, variables can be watched, etc.

see GitHub - maxgerhardt/pio-spi-mock

1 Like

Well, bad news. In the crucial AD7124_ReadData() function, the Due indeed receives 0xFF, 0xFF, 0xFF as returned data, resulting in the above number of 16777215 (=0xFFFFFF).

That’s also visible in the Logic traces

The 0x42 is the read ADC data command, followed by 0x49 to read the channel configuration for channel 0, followed by 0x09 to write the channel configuration for channel 0 (with the data 0x00 0x22). The SPI data 0x49 seems to be quite unqiue and together with the 0x42 and 0x09 commands the read data transfers can be identified easily.

When one compares that with the Uno traces

while the processing delay between the SPI packets is higher (understandable since the Uno is a slower machine), it does not get all 0xff as the response for read ADC data (0x42). It instead receives 0xD8, 0x31, 0xBE.

However, that’s still quite a large number written in decimal (14168510). The Uno in the screenshot only shows “_ADC CJ code = -3439” and similiar.

But that’s actually a bug in the code. The print code

with

Serial.println((int)_ADCValue0[i]);

does a downconversion from the native type of _ADCValue0[i], which is int32_t, to int, which on an Uno is int16_t, but on a due is again int32_t.

So 2 takeaways:

  1. The Due actually receives 0xFFFFFF as the ADC conversion result via SPI. Not sure why.
  2. The Uno’s printed _ADC CJ code value is wrong because of a downcast.

In the code above, can you remove the (int) cast from both _ADCValue0[i] and _ADCValue1[i] and let the program run again on the Uno? What’s the output this time?

1 Like

The output for the UNO still works even after changing this, it seems.
Here is the output:

Do you think that making this change on the DUE would be beneficial as well?

On the Due it makes no difference because int is already int32_t, so no down-cast of the source data happens actually.

So yeah thanks to the real _ADC CJ and _ADC TC codes I was able to, as a test, force the program to take the Uno’s readings and use them for the computation, and that works.

That proves that if the Due had received the right input data via SPI from the chip, it would have also computed the right values.

So the problem lies solely in the fact the Due gets 0xFFFFFF as the ADC conversion result from the AnalogDevices chip and the Uno gets the real data.

The basic readout method is in

And I’m not quite sure what the delay(100); is for other than arbitratrary slowdown or stabilization. But the due takes 99.92 ms and the Uno 100.04ms. Just for fun, can you 1. remove the delay 2. make the delay double 3. make the delay half and see what happens?

The other path would be to try and use a different library that may behave differently. The basic chip is AD7124-8 (on a CN0391 board( for which there is also very similiarly

so if you can write the same channel configurations that the original CN0391 code does with this library, you might get a good result.

On the other hands, you can ask the AnalogDevices engineers that, given the traces from the Due and the Uno, why does the Due get a ADC Data (conversion result) of 0xFFFFFF while the Uno gets the good data? They should know their chip best.

So I have spent so much time on this that I am actually going to move forward and just try to use Modbus functionality to communicate the data from the UNO to the DUE. I have spent too much time stagnant in the same location.
I may not have ever used Modbus, but I understand that there is more than likely much more support on how to get this working.

I also have given up with trying to work with Analog Devices as it seems they just want to get you out of their hair, rather than stick with the issue until it is resolved.