View previous topic :: View next topic |
Author |
Message |
PrinceNai
Joined: 31 Oct 2016 Posts: 463 Location: Montenegro
|
|
Posted: Thu Jun 15, 2023 6:21 pm |
|
|
int8 0 frustration, my friend :-). Your goal is to post a question as specific as you can. So, a piece of code and what you want to achieve with it. The problem you have. The goal of everyone here is to help you, if the question is understandable. That is why there are questions regarding your code. To understand your problem. Some suggestions, if needed or not. When that is done, the first 90% of the solution will take the first 90% of the time and answers through iterations of your code. The remaining 10% will take the remaining 90% of the time. It works, believe it or not. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Fri Jun 16, 2023 1:02 am |
|
|
OK.
I2C addresses are a consistent source of annoyance for everyone. If you
actually look at the datasheet for the ADXL, the manufacturer there is
very sensible, and gives both figures. So on page 17 for example:
Quote: |
With the ALT ADDRESS pin high, the 7-bit
I2C address for the device is 0x1D, followed by the R/W bit. This
translates to 0x3A for a write and 0x3B for a read.
|
This is one of the nicest descriptions of this I have seen.
The point is that I2C has a '7 bit address', but this has to be sent to the
chip as the high seven bits of an 8bit value, with the R/W bit as the
bottom bit.
So a device with a 7bit address of 0x1D, has to be talked to on the bus
with address bytes of 0x3A for a write, and 0x3B for a read.
Now the transaction to an I2C device has as it's first byte, the 'address',
and it is this byte that the bus scanner returns.
The '7bit device address' is half the numbers the scanner returns, and
half the number that has to be sent to actually address the device.
If you are talking about the 'address byte', this is the 8bit value that
has to be sent.
Now, why the designers of I2C, decided to put the R/W bit at the bottom
of the register, and not the top, is a question that has never really been
answered satisfactorily. It means that the user must get clear in their
head the difference between the logical address, and the physical byte
that has to be used.
Some comments
First of all your chip supports 8MHz from the internal clock. Use this.
Pointless to run slower unless you are trying to same uW of power.
Then your response posted:
TCA Port 1#
Found 0X34
Tells you a device has been found on bus 1 at address 0x34. Now this
is a bit puzzling. Are you absolutely sure of the part numbers of the sensors
used?. The point is the ADXL345, is not means to be on this address.
Now chips can often be bought with custom I2C addresses (AD offer
this on these), so it suggests the chips fitted to the board you have are
not on the default addresses. Normally this is shown in the part number
on the device.
The second puzzling thing is that no chip was found on bus 0. You were
saying that you had a device on this bus as well. So look very carefully
at the wiring for this device. Or is this the one you tried to run with 5v
connections?. If so then I'm afraid it was destroyed. |
|
![](templates/subSilver/images/spacer.gif) |
Blackjackmaster
Joined: 14 May 2023 Posts: 30
|
TCA9548A |
Posted: Fri Jun 16, 2023 7:28 am |
|
|
This is the code for the Arduino.
Code: | /**
* TCA9548 I2CScanner.ino -- I2C bus scanner for Arduino
*
*
*/
#include "Wire.h"
#define TCAADDR 0x70
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
// standard Arduino setup()
void setup()
{
while (!Serial);
delay(1000);
Wire.begin();
Serial.begin(115200);
Serial.println("\nTCAScanner ready!");
for (uint8_t t=0; t<8; t++) {
tcaselect(t);
Serial.print("TCA Port #"); Serial.println(t);
for (uint8_t addr = 0; addr<=127; addr++) {
if (addr == TCAADDR) continue;
Wire.beginTransmission(addr);
if (!Wire.endTransmission()) {
Serial.print("Found I2C 0x"); Serial.println(addr,HEX);
}
}
}
Serial.println("\ndone");
}
void loop()
{
} |
This is what I receive:
TCA9548 Scanner is Ready:
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: EE
Number of i2c chips found: 16
Bus Array:
238
C0-DC do not go through the TCA9548A. This chip ALS31313 is controlled with voltage for addressing.
Quote: | . An alternate
I2C address of 0x53 (followed by the R/W bit) can be chosen by
grounding the SDO/ALT ADDRESS pin (Pin 12). This translates to
0xA6 for a write and 0xA7 for a read.
|
This is what the data looks like when I connect to the PIC16F877A directly to the ADXL345. The Address is A6.
TCA9548 Scanner is Ready:
ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: EE
Number of i2c chips found: 17
Bus Array:
238
When the address show up in the Arduino code it is 96-110, not C0-DC.
TCA9548A Data
This is what the output looks like from Arduino. The address is different with the ADXL address.
[img]https://learn.adafruit.com/assets/27691[/img]
This is what I expected to see for each port/channel.
Thanks.... |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Fri Jun 16, 2023 7:53 am |
|
|
One glaring thing here is that the Arduino code is for a TCA chip with
A0, A1 & A2 wired low, but you say yours has these pins wired high. That
is why the 7bit address is 0x70, not 0x77. 0x77*2 is 0xEE, while 0x70*2
is 0xE0.
The scan shows the TCA being found at EE, which then means it won't
be switching the bus, since the code tries to talk to it at 0xE0..... |
|
![](templates/subSilver/images/spacer.gif) |
Blackjackmaster
Joined: 14 May 2023 Posts: 30
|
TCA9548A |
Posted: Fri Jun 16, 2023 9:46 am |
|
|
I am receiving E0 now.
Code: | printf("\n\rTCA9548 Scanner is Ready:\n\r");
for (int8 t=0; t<8; t++) {
select_bus(t);
printf ("\n\rTCA Port #: %u",t);
for (int8 addr=0; addr<=127; addr++) {
if (addr == TCAaddr) continue;
i2c_start ();
i2c_write(addr);
if (!i2c_stop())
{
printf ("\n\rFound I2C 0x%02x", addr); |
I am getting an error here:
*** Error 51 "U:\CCS C\I2C Scanner\TCA9548.c" Line 62(15,16): A numeric expression must appear here
I tried t,TCAaddr, and addr. Not sure what else to try.
The TCA will not pick up the port with PIC16F877A. I ran this hardware on the Arduino board and works fine.
Any suggestions? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 16, 2023 11:01 am |
|
|
Download the CCS manual and put it on your Windows desktop.
https://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Look up i2c_stop() on page 319. The return value is listed as undefined.
You can't do an if() on it and have it be useful. Look at i2c example code on
this forum. Nobody does an if() on i2c_stop(). |
|
![](templates/subSilver/images/spacer.gif) |
Blackjackmaster
Joined: 14 May 2023 Posts: 30
|
TCA9548A |
Posted: Fri Jun 16, 2023 12:11 pm |
|
|
I did take a look at page 319.
My issues is I want to know when a device is connected to the TCA chip. Currently the program list all the available addresses of Port 0 00-255. I only want the address of what is connected to the port. any suggestions? |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9168 Location: Greensville,Ontario
|
|
Posted: Fri Jun 16, 2023 3:24 pm |
|
|
You should be able to modify PCMP's 'I2C scanner' program in the code library.
Actually modify a COPY of it NOT the original......
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Sat Jun 17, 2023 1:18 am |
|
|
That is what he has as the basis of his get_ack_status, at the very start
of the thread. |
|
![](templates/subSilver/images/spacer.gif) |
PrinceNai
Joined: 31 Oct 2016 Posts: 463 Location: Montenegro
|
|
Posted: Sat Jun 17, 2023 5:50 am |
|
|
I put together code from Mr.Ttelmah for selecting channels and PCM's I2C scanner. Scanner is inside one function to make main() easier to read. Names of some variables are changed so they are easier to read for me. I don't have your hardware, so I get 8 "Nothing found" from the code. Try it, maybe it works :-). Note that I forgot to clear device count before each channel is selected, so it will just count on.
Edit: corrected that, trimmed down the range of the scanner to avoid mux own address from being scanned.
Edit2: corrected how select_bus() is called
Code: |
#include <18F46k22.h>
#device ADC=16
#device ICD=TRUE
//#fuses HS
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=8000000)
#use rs232(baud=9600,parity=N,UART2,bits=8,stream=RS232,errors)
#use i2c(Master, slow,i2c1,force_hw)
unsigned int8 I2C_Address;
unsigned int8 status;
unsigned int8 Device_Count = 0;
int8 Channel;
#define TCAaddr 0xEE //for A0,A1,A2=0b111
const int8 bus_array[8]={1,2,4,8,16,32,64,128};
void select_bus(int bus)
{
if (bus > 7 )
return; //trap illegal bus numbers
I2C_start();
I2C_write(TCAaddr);
I2C_write(bus_array[bus]); //select specified bus number
I2C_stop(); //I2C bus now routes to BUS number
}
//Then with the ADXL wired as described above, simply call
// select_bus(0);
//And the ADXL will now be connected to the I2C bus with level
//translation.
//You then write to the ADXL as normal.
int8 get_ack_status(int8 address)
{
int8 ack;
i2c_start();
delay_us(20);
ack = i2c_write(address); // Status = 0 if got an ACK
i2c_stop();
delay_us(20);
if(ack == 0)
return(TRUE);
else
return(FALSE);
}
void Get_I2C_Addresses(void){
// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.
// for(I2C_Address = 0x10; I2C_Address < 0xF0; I2C_Address+=2) // original
for(I2C_Address = 0x10; I2C_Address < 0xE8; I2C_Address+=2) // trimmed down to avoid scanning mux address, just in case
{
status = get_ack_status(I2C_Address);
if(status == TRUE)
{
printf("ACK addr: %X\n\r", I2C_Address);
Device_Count++;
delay_ms(100);
}
}
if(Device_Count == 0){
printf("Nothing Found\n\r");
delay_cycles(1);
}
else{
printf("Found: %u\n\r", Device_Count);
delay_cycles(1);
}
}
//=================================
void main(){
output_float(PIN_B0);
output_float(PIN_B1);
for(Channel = 0; Channel < 8; Channel++){ // loop through channels
select_bus(Channel);
printf("\n\rI2C Channel: %u\n\r", bus_array[Channel]);
Device_Count = 0;
Get_I2C_Addresses(); // complete I2C scanner as a function for a simpler main
}
while(1);
}
|
Last edited by PrinceNai on Wed Jun 21, 2023 10:48 am; edited 3 times in total |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Sat Jun 17, 2023 6:56 am |
|
|
Just trim the count used for the scan 'down', below the address for the
multiplexer. So 0xE8 (say).
Problem is that the multiplexer is designed to load it's configuration
byte immediately after when it sees it's address. The data sheet for it does
not say what happens if it sees a stop at this point, so better to be safe
and not scan it's address.
Neatly done. ![Very Happy](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Blackjackmaster
Joined: 14 May 2023 Posts: 30
|
TCA9548A |
Posted: Mon Jun 19, 2023 9:09 am |
|
|
Hello,
Thank you to all that are responding.
I am able to see all the chips on the I2C that have voltage controlled addressing. I want to know how to get the addresses from the TCA. Here is what I receive from the Arduino code when I scan the TCA chip:
TCAScanner is ready
TCA Port #0
TCA Port #1
Found I2C 0x1E
TCA Port #2
TCA Port #3
Found I2C 0x1E
TCA Port #4
TCA Port #5
TCA Port #6
TCA Port #7
This tells me that I have a device connected to Channel 1 and Channel 3. These are ADXL345 chips. From here I can use select_bus (1) and read from the sensor. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Mon Jun 19, 2023 9:38 am |
|
|
What Prince Nai posted should already do that for you. Just change
the loop to:
Code: |
void main(void)
{
output_float(PIN_B0);
output_float(PIN_B1);
for(Channel = 0; Channel < 8; Channel++)
{ // loop through channels
select_bus(bus_array[Channel]);
printf("\n\rTCA Port #%d",Channel);
Device_Count = 0;
Get_I2C_Addresses(); //I2C scanner
}
while(1);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Blackjackmaster
Joined: 14 May 2023 Posts: 30
|
TCA9548A |
Posted: Mon Jun 19, 2023 11:21 am |
|
|
Hello,
This is the data from the code:
TCA Port #0ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
TCA Port #1ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
TCA Port #2ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
TCA Port #3ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
TCA Port #4ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
TCA Port #5ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
TCA Port #6ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
TCA Port #7ACK addr: A6
ACK addr: C0
ACK addr: C2
ACK addr: C4
ACK addr: C6
ACK addr: C8
ACK addr: CA
ACK addr: CC
ACK addr: CE
ACK addr: D0
ACK addr: D2
ACK addr: D4
ACK addr: D6
ACK addr: D8
ACK addr: DA
ACK addr: DC
ACK addr: E0
Found: 17
These are on the I2C Bus but none of them are going through the TCA. There is one sensor on the TCA and that is on Port 1 which does not show up. 0xE0 is the TCA.
Here is why I need this or equivalent chip. I have one board with 16 sensors on it. The product design can have up to 16 x 6 = 96 sensors. I have already used the the 16 addresses from the voltage levels with the sensor 96-110,0.
Is it possible the PIC16F877A is not compatible with I2C multiplexing? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 19, 2023 12:42 pm |
|
|
Is your test circuit setup like Figure 13 in this pdf ?
https://www.ti.com/lit/ds/symlink/tca9548a.pdf
Do you have pull-ups in all the places that the schematic shows ?
It shows 19 pullup resistors. Do you have them all in your test circuit ?
What are the values of the pull-ups ?
Do you have the 3 pullup resistors shown on the left side of the TCA9548A ?
What are their values ?
The schematic list several voltages: VdPUM, Vcc, and VdPUx.
What voltages are you using for each of those ? |
|
![](templates/subSilver/images/spacer.gif) |
|