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

[ADC] Pick external ADC, and develop communication #110

Closed
rgw3d opened this issue Jan 16, 2019 · 9 comments · Fixed by #159
Closed

[ADC] Pick external ADC, and develop communication #110

rgw3d opened this issue Jan 16, 2019 · 9 comments · Fixed by #159
Assignees

Comments

@rgw3d
Copy link
Member

rgw3d commented Jan 16, 2019

Once we have a new ADC, we will need to communicate with it over SPI or I2C (likely). How do we do this communication reliably?

@rgw3d
Copy link
Member Author

rgw3d commented Jan 16, 2019

For i2c something like this could be implemented in C++ https://raspberry-projects.com/pi/programming-in-c/i2c/using-the-i2c-interface

@schmidtwmark
Copy link
Contributor

It may be worthwhile to clone ADCManager and make two versions--ExternalADCManager and BuiltInADCManager. If they are accessing two different components, they should be on separate refresh loops.

@rgw3d
Copy link
Member Author

rgw3d commented Feb 28, 2019

We are using the ADS1115: https://www.adafruit.com/product/1085

On the BBB, use command i2cdetect -y -r 2 to look for i2c devices on /dev/i2c-2

From Adafruit:
I2C Addressing
The ADS11x5 chips have a base 7-bit I2C address of 0x48 (1001000) and a clever addressing scheme that allows four different addresses using just one address pin (named ADR for ADdRess). To program the address, connect the address pin as follows:

    0x48 (1001000) ADR -> GND
    0x49 (1001001) ADR -> VDD
    0x4A (1001010) ADR -> SDA
    0x4B (1001011) ADR -> SCL

@rgw3d
Copy link
Member Author

rgw3d commented Feb 28, 2019

More debug information: kelly/node-i2c#27

@rgw3d rgw3d self-assigned this Feb 28, 2019
@rgw3d
Copy link
Member Author

rgw3d commented Feb 28, 2019

@rgw3d
Copy link
Member Author

rgw3d commented Feb 28, 2019

The the TI site as well: http://www.ti.com/lit/ds/symlink/ads1115.pdf

@rgw3d
Copy link
Member Author

rgw3d commented Mar 7, 2019

Now that the low-level structure is developed on the branch pod4-i2c, we can use the interface!

Our goal: Read all 4 of the analog ports from each of ADCs that we have connected over i2c. Since each read takes about 3 milliseconds, we are only going to read one port per refresh().

We are going to be doing something very similar to what is already implemented in TMPManager.hpp. The TMPData struct is very similar. The way that the idx variable within the refresh() loop is very similar to what we want to accomplish

First thing to do is to modify the I2Cdata structure, such that we can store the data we read in into it. It is defined at the top of I2CManager.hpp, and only has a dummy variable. Since we know that all of our data will be int16_ts, (since this is a 16-bit adc), then we can simply create an array within the struct. Something like int16_t data[8] would work (maybe with a more descriptive name). Once this is implemented, then we can try to take on the refresh() loop.

For the refresh loop we want to read one value at a time, while still traversing all of the different ports, while keeping code size small. Look at how TMPManager.cpp does it. Look at line 27 to see that we open a file based on a value idx, which you can see that on line 50 we increment (and set back to 0 once we have covered all the values, that's what the modulo % operator does). The idx value is an index into an array which you can find defined in TMPManager.hpp.
You can ignore most of what TMPManager.cpp actually does, but the key part is what i listed above -- an index is used to select a variable from an array, which is used to selectively read in sensor data.

For the I2CManager.cpp refresh() loop, I'd approach it this way:
Identify what stays the same every loop. (hint, it is i2c_fd)
Identify what can change after a loop (hint, it is the 0x48 vs 0x49 nodeID, and the ANC0 vs ANC1... vs ANC3)

So, in a way similar to how TMPManager.cpp accomplishes it, we want to do:

int16_t value = 0;
if(!set_i2c_addr(i2c_fd,     /* ACCESS NODEID BASED ON INDEX */ 0x48             )){
     return false;
}
if(single_shot(i2c_fd, /* ACCESS PORT BASED ON INDEX */ ANC0, value)){
    print(LogLevel::LOG_INFO, "i2c val1: %d, in micros: %lu\n", value, b-a);
}

//STORE VALUE BASED ON INDEX
//INCREMENT INDEX

@anshulshah957
Copy link
Contributor

What values are being used through the external ADC? Just the accelerometers?

@rgw3d
Copy link
Member Author

rgw3d commented May 2, 2019

Internal ADCs handle Accelerometers
External ADCs handle temperature

@rgw3d rgw3d mentioned this issue Jul 13, 2019
@rgw3d rgw3d closed this as completed in #159 Aug 9, 2019
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

Successfully merging a pull request may close this issue.

3 participants