Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPI communication troubles #88

Closed
nariox opened this issue Oct 22, 2024 · 7 comments
Closed

SPI communication troubles #88

nariox opened this issue Oct 22, 2024 · 7 comments

Comments

@nariox
Copy link

nariox commented Oct 22, 2024

This is somewhat related to #37 .

I have a student implementing support for an MCP3008 (an 8-channel 10-bit ADC chip) via telemetrix. The MCP3008 does not work directly with 8-bit registers, rather relying on asynchronous alignment of the transmission of data (see sections 5 and 6 of the datasheet), where the IC waits until a 1 is transmitted (start bit) followed 4-bits of the desired information (1 bit to define if we want differential or single-ended, then 3-bits to define the desired channel).

After receiving the command, the ADC samples the signal for one SCK clock cycle and starts transmitting the signal on the following cycle (prepended by a start bit of 0). The whole message is 11 bytes (10 valid bits and the null start bit).

One way the datasheet suggests implementing communication with 8-bit register communication is by zero-padding the message on the left until we are ready to receive the signal. Their recommendation is sending 0b00000001, followed by DIFF CH2 CH1 CH0 and then 4 don't-care bits. The ADC starts sampling while the 5th bit is being transmitted and then transmits the null start bit followed by 2 ADC bits. During the 3rd transmission (8-bits of don't care), the ADC transmits the remaining 8 bits.

To use the MCP3008 with telemetrix, we would need to make a few changes (assuming bit-banging is not an option). First, we could change spi_read_blocking to allow the first byte to be returned (similar to what was proposed in #37).

Alternatively, we could either change spi_read_blocking to allow sending a list of registers so we could do as suggested by the datasheet. The third option would be to communicate first byte to be [0 0 1 DIFF CH2 CH1 CH0] (or [0 0 0 1 DIFF CH2 CH1 CH0 0] ) then capture the second and third byte responses.

While the third option looks like it should work, this line prevents it from working as the MSB of the first byte is forced high. Solution 2 would also require this behavior to change.

I am not sure what would be the best path forward. Solution 1 and 2 requires some changes in the API, which could break compatibility with previous versions. Solutions 2 and 3 would require changes in the Telemetrix4Arduino (and potentially all other boards). We might be able to create a different sofware path for telemetrix.py to take depending on the version of the board, but that might be a large-ish undertaking.

What do you think Mr. Y?

To implement

@nariox
Copy link
Author

nariox commented Oct 22, 2024

(I'd like to add, that for the time being, I am using the little-endian mode, but I'd like to find a less hackish solution).

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 22, 2024

Thanks for the question. I think the simplest and safest way to solve the issue is to fork Telemetrix and/or Telemetrix4Arduino and make the changes specific to the device's needs. You would then have the option to create the student's own repository, or I could publish the changes as an MPC3008 branch off of the main branch.

At this point, I am not receptive to incorporating the changes into the main branch since I have no way of testing the device. I feel this is a low-risk approach since the likelihood of telemetrix and/or Telemetrix4Arduino changing in the future is very low.

Please let me know your thoughts.

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 23, 2024

Looking at the Adafruit support library, I may have a solution that can be incorporated into the master branch with minimum risk.

If I add a parameter to

spi_read_blocking(self, register_selection, number_of_bytes_to_read, call_back=None)

Like so:

spi_read_blocking(self, register_selection, number_of_bytes_to_read, call_back=None, read_bit=True)

If read_bit is true, then

SPI.transfer(command_buffer[2] | 0x80);

The transfer in Telemetrix4Arduino would remain the same.

If False, the transfer would look like this:
SPI.transfer(command_buffer[2] );

Please let me know if this proposal solves the issue.

It would then be your student's application's responsibility to interpret the data returned from a spi_read_blocking call in telemetrix.

@nariox
Copy link
Author

nariox commented Oct 23, 2024 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 23, 2024

Ok. I will implement it and let you know when it is done.

MrYsLab added a commit that referenced this issue Oct 23, 2024
MrYsLab added a commit that referenced this issue Oct 24, 2024
Addresses issue #88
@MrYsLab
Copy link
Owner

MrYsLab commented Oct 24, 2024

I just published version 5.4.3 of Telemetrix4Arduino.
I also released version 1.41 of teletmetrix.

The user guide was also updated.

@MrYsLab MrYsLab closed this as completed Oct 24, 2024
@nariox
Copy link
Author

nariox commented Oct 28, 2024 via email

MrYsLab added a commit that referenced this issue Nov 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants