I can't explain this code behaviour and need help

Dear reader
I have a I2C scanner code that prints out I2C addresses and if a device is connected to the I2C bus or not. It works perfect for the first 0...123 addresses till the last line 4...127 needs to be printed

My question : how is it possible that the last line of addresses is printed after the "#2#" while the code illustrates that this is not possible. Hope someone can tell me.

This code is run on an ESP8266 and uses the Arduino libraries.
The same code run on a ATmega 328 does not show this strange behavior.

This is the code

#include  <arduino.h>
#include  <Wire.h>

#define	  STOP		      true
#define     MASTER_ADR    0x01
#define     SDA_PIN       13       // GPIO4, PCB-D2 can be any free pin on ESP8266         
#define     SCL_PIN       12       // GPIO5, PCB-D1 can be any free pin on ESP8266        

uint8_t I2C_scan(uint8_t mode){         // mode0=no output, Mode1= Summery, mode2=full output

    uint8_t device_cnt=0, I2C_adr=0, cnt;
    uint8_t rc, colcnt=0, collumns=4;
    
//    struct I2C_devices {
//     uint8_t         I2C_adr;
//     const char*     deviceID;
//     const char*     type;
//     } I2Cdevice[]={{0x36,"AS5600","Magn Rotary"},{0x27, "PCF8574","GPIO(diplay)"},{0x3C,"DS1306","OLED-Disp"}, {0x68,"DS3231","RTC"}, 0x57, "AT24C32", "2KB Mem" };
    struct I2C_devices {
    uint8_t         I2C_adr;
    const char      *deviceID;
    const char      *type;
    } 

    I2Cdevice[]={
    {0x36,"AS5600","Magn Rotary"},
    {0x27, "PCF8574","GPIO(diplay)"},
    {0x3C,"DS1306","OLED-Disp"},
    {0x68,"DS3231","RTC"},
    {0x57, "AT24C32", "2KB Mem"},
    };



    switch (mode){
        case 2 : { 
            printf("\nI2C Scanner\n");
            for(cnt= 1; cnt <= 14*collumns+5; cnt++) printf("%s","=");
            printf("\n     ");
            for(colcnt=0;colcnt<collumns;colcnt++)  printf("%6s%02u%6s","",colcnt,"|");
            
            for(I2C_adr = 0; I2C_adr <= 127; I2C_adr++) {
                Wire.beginTransmission(I2C_adr);
                rc = Wire.endTransmission();
                if ( ((I2C_adr)%collumns)==0) printf("\n %03u\t", I2C_adr); 
//                printf("0x%02X = %3s  | ",I2C_adr, rc ? " - " : "Fnd");
                if (rc) printf("0x%02X = %s  | ", I2C_adr, " - ");
                else    printf("0x%02X = %s  | ", I2C_adr, "Fnd");
            }
            printf("\n");
            for(cnt= 1; cnt <= 14*collumns+5; cnt++) printf("%s","=");
            printf("\n");

        } //break;

        case 1 : {
            printf("I2C active devices:\n");
            device_cnt=0;
            for(I2C_adr = 0; I2C_adr <= 127; I2C_adr++) {
                Wire.beginTransmission(I2C_adr);
                rc = Wire.endTransmission();
                if(!rc) {  
                    device_cnt++;
                    for (cnt=0; cnt<=(sizeof(I2Cdevice)/sizeof(I2Cdevice[0])-1); cnt++){
                        if(I2C_adr==I2Cdevice[cnt].I2C_adr) printf("0X%02X,  ID= %10s,  %s\n",I2Cdevice[cnt].I2C_adr, I2Cdevice[cnt].deviceID, I2Cdevice[cnt].type);
                    }
                }
            }
            printf("Nr of found I2C devices : %u\n\n", device_cnt); 
        }

        case 0:{   
            device_cnt=0;
            for(I2C_adr = 0; I2C_adr <= 127; I2C_adr++) {
                Wire.beginTransmission(I2C_adr);
                rc = Wire.endTransmission();
                if(!rc) device_cnt++;
            }
        }
    }
    return  device_cnt;
} 

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN, MASTER_ADR);  // join i2c bus (address optional for master)
  ///Wire.setClock(400000L); // default 100Khz uncommend if 400Khz is needed
  I2C_scan(2);
}

void loop() {	
}

This is the printed output

Post ALL the code. The error is in the part you did not post.

1 Like

Added the whole routine now. I hope your are right but I can't see it.

That is not all the code.

The forum rules expect you post all of the code, from start to finish, or the minimum example that can be compiled, run and reproduces the error.

In order to make sense of your masterpiece, forum members need to see, for example, how all variables are declared and defined.

The same code run on a atmega 328

The posted code won't compile without errors for the ATmega328, regardless.

1 Like

You need break statements at the end of each case block.

If not, the code will simply continue into the next block.

1 Like

I'd suspect there is some weird buffer stuff going on inside the printf() implementation. What is your printf(), anyway?

Following that hunch, I'd try to move the line feeding part of the if()-clause to the end of the for()-loop, of course modifying it to

if ( ((I2C_adr+1)%collumns)==0) printf("\n");

and eliminating the "\n" from the first if()-clause.

Jan

Very dangerous, and not legal in C++.

This on the other hand is fine.

The OP's version seemed to have a syntax error, or I did not understand it.

struct I2C_devices {
    uint8_t I2C_adr;
    const char *deviceID;
    const char *type;
} I2Cdevice[]={
    {0x36,"AS5600","Magn Rotary"},
    {0x27, "PCF8574","GPIO(diplay)"},
    {0x3C,"DS1306","OLED-Disp"},
    {0x68,"DS3231","RTC"},
    {0x57, "AT24C32", "2KB Mem"},
};

Obvsly this means no wiritng into those character strings.

HTH

a7

Hi, @wogoos
Please do not go back and update older posts, it makes the thread harder to follow by other people looking for similar solutions.

Thanks.. Tom... :smiley: :+1: :australia:
PS. I'm off to bed, 1:24am here... :sleeping: :sleeping: :sleeping:

1 Like

output when i run your code
needed to define char* as const char*

    struct I2C_devices {
        uint8_t I2C_adr;
        const char*   deviceID;
        const char*   type;
I2C Scanner
=============================================================
           00     |      01     |      02     |      03     |
 000	0x00 =  -   | 0x01 =  -   | 0x02 =  -   | 0x03 =  -   | 
 004	0x04 =  -   | 0x05 =  -   | 0x06 =  -   | 0x07 =  -   | 
 008	0x08 =  -   | 0x09 =  -   | 0x0A =  -   | 0x0B =  -   | 
 012	0x0C =  -   | 0x0D =  -   | 0x0E =  -   | 0x0F =  -   | 
 016	0x10 =  -   | 0x11 =  -   | 0x12 =  -   | 0x13 =  -   | 
 020	0x14 =  -   | 0x15 =  -   | 0x16 =  -   | 0x17 =  -   | 
 024	0x18 =  -   | 0x19 =  -   | 0x1A =  -   | 0x1B =  -   | 
 028	0x1C =  -   | 0x1D =  -   | 0x1E =  -   | 0x1F =  -   | 
 032	0x20 =  -   | 0x21 =  -   | 0x22 =  -   | 0x23 =  -   | 
 036	0x24 =  -   | 0x25 =  -   | 0x26 =  -   | 0x27 =  -   | 
 040	0x28 =  -   | 0x29 =  -   | 0x2A =  -   | 0x2B =  -   | 
 044	0x2C =  -   | 0x2D =  -   | 0x2E =  -   | 0x2F =  -   | 
 048	0x30 =  -   | 0x31 =  -   | 0x32 =  -   | 0x33 =  -   | 
 052	0x34 =  -   | 0x35 =  -   | 0x36 =  -   | 0x37 =  -   | 
 056	0x38 =  -   | 0x39 =  -   | 0x3A =  -   | 0x3B =  -   | 
 060	0x3C =  -   | 0x3D =  -   | 0x3E =  -   | 0x3F =  -   | 
 064	0x40 =  -   | 0x41 =  -   | 0x42 =  -   | 0x43 =  -   | 
 068	0x44 =  -   | 0x45 =  -   | 0x46 =  -   | 0x47 =  -   | 
 072	0x48 =  -   | 0x49 =  -   | 0x4A =  -   | 0x4B =  -   | 
 076	0x4C =  -   | 0x4D =  -   | 0x4E =  -   | 0x4F =  -   | 
 080	0x50 =  -   | 0x51 =  -   | 0x52 =  -   | 0x53 =  -   | 
 084	0x54 =  -   | 0x55 =  -   | 0x56 =  -   | 0x57 =  -   | 
 088	0x58 =  -   | 0x59 =  -   | 0x5A =  -   | 0x5B =  -   | 
 092	0x5C =  -   | 0x5D =  -   | 0x5E =  -   | 0x5F =  -   | 
 096	0x60 =  -   | 0x61 =  -   | 0x62 =  -   | 0x63 =  -   | 
 100	0x64 =  -   | 0x65 =  -   | 0x66 =  -   | 0x67 =  -   | 
 104	0x68 =  -   | 0x69 =  -   | 0x6A =  -   | 0x6B =  -   | 
 108	0x6C =  -   | 0x6D =  -   | 0x6E =  -   | 0x6F =  -   | 
 112	0x70 =  -   | 0x71 =  -   | 0x72 =  -   | 0x73 =  -   | 
 116	0x74 =  -   | 0x75 =  -   | 0x76 =  -   | 0x77 =  -   | 
 120	0x78 =  -   | 0x79 =  -   | 0x7A =  -   | 0x7B =  -   | 
 124	0x7C =  -   | 0x7D =  -   | 0x7E =  -   | 0x7F =  -   | #1#
=============================================================
#2#

I'm getting the same result, only that "#1#" starts on a new line.

Time for OP to remember the thread and tell us more.

Jan

Hi Red car,
Breaks are not always required. I want depending on the mode value 0,2,1 to run through all case statements. Mode 2 give you all info including an address table. Mode 1 only lists devices and a total count of found devices. Mode 0 has no output, it only returns a value on the function call indicating the amount of devices is found.
I hope this helps.

Hi GCJR
That is a good tip I did see compiler warning on that one (needed to define char* as const char*). Normally I take these warning serious but this time I overlooked them. I'm gone to change that part of the code. I will check the code and see if that generates the same results on this side. What you print is the output I expect fingers crossed and see if I have the same results.
I will let you know by this forum what the outcome is, and I thank you very much

Thanks jan I have received some tips to correct my code. I will test it and if I have the results as I expect I will post it. I appreciate your input in this.

Hi GCJR
I have added all the suggestions you gave to my code and compiling in VSC doesn't show any errors. I updated the problem description now with the full code and updated also the output.

Unfortunately, I still have the weird outcome. It prints till address #123 and the line with address 124 show up unexpected later, not in line with the sequence of printf() Statements.
My question is If you compile and run the code as I have it on a ESP8266 do you see the same output or not. If you don't and I do, I must have something messed up in my development platform.

Hi, @wogoos

READ POST #9....

Tom.. :smiley: :+1: :coffee: :coffee: :coffee: :australia:

you're not crazy!

output from Nodemce V3


 080	0x50 =  -   | 0x51 =  -   | 0x52 =  -   | 0x53 =  -   | 
 084	0x54 =  -   | 0x55 =  -   | 0x56 =  -   | 0x57 =  -   | 
 088	0x58 =  -   | 0x59 =  -   | 0x5A =  -   | 0x5B =  -   | 
 092	0x5C =  -   | 0x5D =  -   | 0x5E =  -   | 0x5F =  -   | 
 096	0x60 =  -   | 0x61 =  -   | 0x62 =  -   | 0x63 =  -   | 
 100	0x64 =  -   | 0x65 =  -   | 0x66 =  -   | 0x67 =  -   | 
 104	0x68 =  -   | 0x69 =  -   | 0x6A =  -   | 0x6B =  -   | 
 108	0x6C =  -   | 0x6D =  -   | 0x6E =  -   | 0x6F =  -   | 
 112	0x70 =  -   | 0x71 =  -   | 0x72 =  -   | 0x73 =  -   | 
 116	0x74 =  -   | 0x75 =  -   | 0x76 =  -   | 0x77 =  -   | 
 120	0x78 =  -   | 0x79 =  -   | 0x7A =  -   | 0x7B =  -   | 

=============================================================
I2C active devices:
 124	0x7C =  -   | 0x7D =  -   | 0x7E =  -   | 0x7F =  -   | Nr of found I2C devices : 0

Hi GCJR
Any idea why this printf() does not prints in line with the code lines, or do I overlook something so obvious that I don't see it ha ha

Sorry Tom
yes you are right I do get it now. yes, you're right, the responses do not stay in line with the original post. I will remember that. In this case, I think it's still in line with the responses.

no

i having similar sequence problems with some of my code and got better results by concatenating sub-strings into a single line using a single printf.

i had also noticed a while back that serial.print() seemed to have priority over printf.