-->
Page 1 of 2

ESP32 Wire I2C

PostPosted: Mon Jul 16, 2018 1:11 pm
by picstart
The default I2c in hardware pins are 21 and 22.
I seems that these can't be changed... I looked at the several (named the same Wire.ccp and Wire.h) none have any in the code space versioning identification so I was forced to rely on the external file dating to guess the most recent. All had different coding of Wire.ccp and Wire,h.
Looks like there is no bit banging software for I2C on the Esp32
Anyway thanks to a soldering iron and two short lengths of insulated copper wire these buried coding features can be worked around. The necessary connections are now soldered to the hardware pins 21 and 22.

Re: ESP32 Wire I2C

PostPosted: Mon Jul 16, 2018 3:48 pm
by btidey
I thought the pin mux capabilities of the chip hardware gave a lot of flexibility in connecting the internal peripherals (like the 2 i2c channels) to different GPIO pads.

The Arduino core has 2 calls pinMatrixOutAttach and pinMatrixOutDetach to give access to the matrix and set up the connections.

I haven't tried this myself but would have thought this could be used to get the i2c on pretty much any GPIO.

Re: ESP32 Wire I2C

PostPosted: Mon Jul 16, 2018 3:55 pm
by btidey
Looking further up the food chain

esp32-hal-i2c.c has things like i2cAttachSCL(i2c_t * i2c, int8_t scl) to attach the pin using the base attach calls.

wire.cpp initialises with

void TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)

which calls i2cAttachSCL(i2c_t * i2c, int8_t scl) and i2cAttachSDA(i2c, sda);

So it looks like you can choose the pins with the Wire initialiser.

Re: ESP32 Wire I2C

PostPosted: Tue Jul 17, 2018 7:47 am
by picstart
I suspect there are only two choices for I2c with the ESP32. I saw the attach calls but again I suspect they are to just configure either choice one or choice two for the two hardware I2C interfaces.
Any the code below is the example for a ds3231 RTC very slightly modified to correctly get the __DATE__ from compile the original example is off a char in __DATE__.
The code only works with the hardware I2C pins it will freeze or crash if other pins are used.
Code: Select all///////// ds3231 is a 3.3v RTC
//     
//                        ESP 32
//                       \/\/\/\/\/\
//                    +--------------+
//           3.3v    -|              |-GND--
//           Reset   -|              |-P23 
//           SVP     -|              |-P22    Note hardwire  SCL
//           SVN     -|              |- Tx
//           P34     -|              |- Rx
//           P35     -|              |-P21   Note hardwired SDA
//           P32     -|              |-GND
//           P33     -|              |-P19 
//           P25     -|              |-P18 
//           P26     -|              |-P5
//           P27     -|              |-P17 
//           P14     -|              |-P18 
//           P12     -|              |-P4 
//           GND     -|              |-P0
//           P13     -|              |-P2  BUILTIN LED
//           SD2     -|              |-P15
//           SD3     -|              |-SD1
//           CMD     -|              |-SD0
//           5V      -|              |-DLK
//                    +--------------+
//                         \____/                 
//           
#include <Wire.h>
#include "ds3231.h"
#include <stdio.h>
#define BUFF_MAX 128
#define DS3231_I2C_ADDR 0x00
uint8_t mytime[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 1000;
/* template for ts declared in the h file
 * struct ts {
    uint8_t sec;         // seconds
    uint8_t min;         // minutes
    uint8_t hour;        // hours
    uint8_t mday;        // day of the month
    uint8_t mon;         // month
    int16_t year;        // year
    uint8_t wday;        // day of the week
    uint8_t yday;        // day in the year
    uint8_t isdst;       // daylight saving time
    uint8_t year_s;      // year in short notation
#ifdef CONFIG_UNIXTIME
    uint32_t unixtime;   // seconds since 01.01.1970 00:00:00 UTC
#endif
};


 */
 ts init_time;

void compile_ts(String date,String time)
{
///parse  __DATE__  Jul  2 2018 __TIME__ 13:40:16
//// used to set time on first compile
//// modified by dk to fix __DATE__ issue
    int pos;
    char cmonth[3];
    String  smonth, sday, syear, shour,smin,ssec;
    int month, day, year, hour,min,sec;
    String  month_names= "JanFebMarAprMayJunJulAugSepOctNovDec";
    smonth=date.substring(0,3);
    pos=month_names.indexOf(smonth);
    sday=date.substring(4,6);
    syear=date.substring(7,11);
    Serial.print("date ");
    Serial.println(date);
    //Serial.println(pos);
    //Serial.println(sday);
    //Serial.println(syear);
   
    //Serial.println(smonth);
    day=sday.toInt();
    month=pos/3+1;
    year=syear.toInt();
   
    shour=time.substring(0,2);
    smin=time.substring(3,6);
    ssec=time.substring(6,8);
    //Serial.println("time");
    //Serial.println(shour);
    //Serial.println(smin);
    //Serial.println(ssec);
    hour=shour.toInt();
    min=smin.toInt();
    sec=ssec.toInt();
    //Serial.println(hour);
    //Serial.println(min);
    //Serial.println(sec);
    hour=shour.toInt();
    min=smin.toInt();
    sec=ssec.toInt();
    init_time.sec=sec;
    init_time.min=min;
    init_time.hour=hour;
   
    init_time.mday=day;        /* day of the month */
    init_time.mon=month;         /* month */
    init_time.year=year;        /* year */
}




void parse_cmd(char *cmd, int cmdsize);

void setup()
{int SDA=21,SCL=22;              /// I2C for ds3231
   Wire.begin(SDA,SCL);
  //   Wire.begin();
     
    Serial.begin(115200);
   
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);
    Serial.println();
    Serial.print(__DATE__);
    Serial.println(__TIME__);
    Serial.println("GET time");
    /*
    init_time.sec=0;
    init_time.min=0;
    init_time.hour=12;
   
    init_time.mday=2;        // day of the month
    init_time.mon=7;         // month
    init_time.year=2018;        // year
    init_time.wday=2;        // day of the week
    //init_time.yday;        // day in the year
    //init_time.isdst;       // daylight saving time
   // init_time.year_s;      // year in short notation
   */
  compile_ts(__DATE__,__TIME__);  // uncomment on first compile
   DS3231_set(init_time);          // uncomment on first compile
   
}

void loop()
{
    char in;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // show time once in a while
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t);

        // there is a compile time option in the library to include unixtime support
#ifdef CONFIG_UNIXTIME
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d %ld", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec, t.unixtime);
#else
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
#endif

        Serial.println(buff);
        prev = now;
    }

    if (Serial.available() > 0) {
        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {
            parse_cmd(recv, recv_size);
            recv_size = 0;
            recv[0] = 0;
        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]
        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
            // drop
            recv_size = 0;
            recv[0] = 0;
        } else if (recv_size < BUFF_MAX - 2) {
            recv[recv_size] = in;
            recv[recv_size + 1] = 0;
            recv_size += 1;
        }

    }
}

void parse_cmd(char *cmd, int cmdsize)
{
    uint8_t i;
    uint8_t reg_val;
    char buff[BUFF_MAX];
    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time
    if (cmd[0] == 84 && cmdsize == 16) {
        //T355720619112011
        t.sec = inp2toi(cmd, 1);
        t.min = inp2toi(cmd, 3);
        t.hour = inp2toi(cmd, 5);
        t.wday = cmd[7] - '0';  ////// ascii to dec
        t.mday = inp2toi(cmd, 8);
        t.mon = inp2toi(cmd, 10);
        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
        DS3231_set(t);
        Serial.println("OK");
    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        Serial.print("aging reg is ");
        Serial.println(DS3231_get_aging(), DEC);
    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            mytime[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        uint8_t flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(mytime[0], mytime[1], mytime[2], mytime[3], flags);
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
        //BMMHHDD
        for (i = 0; i < 4; i++) {
            mytime[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
        }
        uint8_t flags[5] = { 0, 0, 0, 0 };
        DS3231_set_a2(mytime[0], mytime[1], mytime[2], flags);
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
        Serial.print("temperature reg is ");
        Serial.println(DS3231_get_treg(), DEC);
    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
        reg_val = DS3231_get_sreg();
        reg_val &= B11111100;
        DS3231_set_sreg(reg_val);
    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
        reg_val = DS3231_get_addr(0x5);
        Serial.print("orig ");
        Serial.print(reg_val,DEC);
        Serial.print("month is ");
        Serial.println(bcdtodec(reg_val & 0x1F),DEC);
    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3231_set_aging(0);
    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
        Serial.print("status reg is ");
        Serial.println(DS3231_get_sreg(), DEC);
    } else {
        Serial.print("unknown command prefix ");
        Serial.println(cmd[0]);
        Serial.println(cmd[0], DEC);
    }
}