thebradleysanders / ESPHome-Arduino-Port-Expander

An Arduino Port Expander for ESPHome with added Arduino Mega 2560 support
12 stars 9 forks source link

Help converting atmega32u4 #4

Open NonaSuomy opened 1 year ago

NonaSuomy commented 1 year ago

Hi @thebradleysanders I see you converted the code for the mega any idea how to convert it for the 32u4?

https://github.com/thebradleysanders/ESPHome-Arduino-Port-Expander/blob/main/arduino_port_expander.h#L34

How do you get the right binary values for the pins?

01 (INT.6/AIN0) PE6
02 UVcc
03 D
04 D+
05 UGnd
06 UCap
07 VBus
08 (SS/PCINT0) PB0
09 (PCINT1/SCLK) PB1
10 (PDI/PCINT2/MOSI) PB2
11 (PDO/PCINT3/MISO) PB3
12 (PCINT7/OC0A/OC1C/RTS) PB7
13 RESET
14 VCC
15 GND
16 XTAL2
17 XTAL1
*18 (OC0B/SCL/INT0) PD0
*19 (SDA/INT1) PD1
20 (RXD1/INT2) PD2
21 (TXD1/INT3) PD3
22 (XCK1/CTS) PD5
23 GND
24 AVCC
25 PD4 (ICP1/ADC8)
26 PD6 (T1/OC4D/ADC9)
27 PD7 (T0/OC4D/ADC10)
28 PB4 (PCINT4/ADC11)
29 PB5 (PCINT5/OC1A/OC4B/ADC12)
30 PB6 (PCINT6/OC1B/OC4B/ADC13)
31 PC6 (OC3A/OC4A)
32 PC7 (ICP3/CLK0/OC4A)
33 PE2 (HWB)
34 VCC
35 GND

Analog
32u4                         324p                                Not defined
36 PF7 (ADC7/TDI)   22 ADC7 
37 PF6 (ADC6/TDO) 19 ADC6 
38 PF5 (ADC5/TMS) 28 PC5 (ADC5/SCL/PCINT13)    26 PC3 (ADC3/PCINT11)
39 PF4 (ADC4/TCK)  27 PC4 (ADC4/SDA/PCINT12)   25 PC2 (ADC2/PCINT10)
40 PF1 (ADC1)          22 PC1 (ADC1/PCINT9)
41 PF0 (ADC0)          23 PC0 (ADC0/PCINT8)

42 AREF
43 GND
44 AVCC

Thank you for any help.

thebradleysanders commented 1 year ago

I will work on this for you, not sure how long it will take, could be quick. It’s been a while since I did this so I’ll have to refresh myself, thanks for the project! What exact board do you have?Sent from my iPhoneOn Oct 27, 2022, at 9:05 PM, NonaSuomy @.**> wrote: Hi @thebradleysanders I see you converted the code for the mega any idea how to convert it for the 32u4? https://github.com/thebradleysanders/ESPHome-Arduino-Port-Expander/blob/main/arduino_port_expander.h#L34 How do you get the right binary values for the pins? 01 (INT.6/AIN0) PE6 02 UVcc 03 D 04 D+ 05 UGnd 06 UCap 07 VBus 08 (SS/PCINT0) PB0 09 (PCINT1/SCLK) PB1 10 (PDI/PCINT2/MOSI) PB2 11 (PDO/PCINT3/MISO) PB3 12 (PCINT7/OC0A/OC1C/RTS) PB7 13 RESET 14 VCC 15 GND 16 XTAL2 17 XTAL1 18 (OC0B/SCL/INT0) PD0 *19 (SDA/INT1) PD1 20 (RXD1/INT2) PD2 21 (TXD1/INT3) PD3 22 (XCK1/CTS) PD5 23 GND 24 AVCC 25 PD4 (ICP1/ADC8) 26 PD6 (T1/OC4D/ADC9) 27 PD7 (T0/OC4D/ADC10) 28 PB4 (PCINT4/ADC11) 29 PB5 (PCINT5/OC1A/OC4B/ADC12) 30 PB6 (PCINT6/OC1B/OC4B/ADC13) 31 PC6 (OC3A/OC4A) 32 PC7 (ICP3/CLK0/OC4A) 33 PE2 (HWB) 34 VCC 35 GND

Analog 32u4 324p Not defined 36 PF7 (ADC7/TDI) 22 ADC7 37 PF6 (ADC6/TDO) 19 ADC6 38 PF5 (ADC5/TMS) 28 PC5 (ADC5/SCL/PCINT13) 26 PC3 (ADC3/PCINT11) 39 PF4 (ADC4/TCK) 27 PC4 (ADC4/SDA/PCINT12) 25 PC2 (ADC2/PCINT10) 40 PF1 (ADC1) 22 PC1 (ADC1/PCINT9) 41 PF0 (ADC0) 23 PC0 (ADC0/PCINT8)

42 AREF 43 GND 44 AVCC

Thank you for any help.

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>

thebradleysanders commented 1 year ago

Better yet, it should work, the only thing that shouldn't is the analog pins, can you try and and let me know if the digital pins work? I don't have a board to test.

NonaSuomy commented 1 year ago

I have not tested the digital pins yet as I wanted to use the analog ones. Will have a look and report back. Seems they have 12 analog pins broken out on this board A0-A11. Currently A0 gives me a value in the 100’s with a 10k pot attached. A1 gives a value in the 10000’s for some reason (thought it was supposed to only be 0-1023) all the rest of the analog just show zero.

68CC263C-BD19-4B0D-A00B-59A26E967FE2 FA0EAC10-C2B2-4A25-A3B8-D220CDDD9462

https://medesign.seas.upenn.edu/index.php/Guides/MaEvArM-adc

NonaSuomy commented 1 year ago

Is it possible to convert the analog pin defined part to use Arduino A0 etc internal pin definitions so these binary values wouldn't be required?

NonaSuomy commented 1 year ago

With the default code base:

GND                                     VCC +5V
00 B0  (00)                            F0 21 A00 (A1 Value:538 Idle: 96)
01 B1  (01)                            F1 20 A01 (A0 Value:32864 Idle: 96)
02 B2  (02)                            F4 19 A02 (?? Output 0)
03 B3  (03)                            F5 18 A03 (?? Output 0)
04 B7  (04)                            F6 17 A04 (?? Output 0)
24 E8  (?? No response)     (Interior)  AREF AF 
05 D0 (SCL)                           F7 16 A05 (?? Output 0)
06 D1 (SDA)                          B6 15 A06 (?? Output 0)
07 D2 (07)                             B5 14 A07 (?? Output 0)
08 D3 (08)                             B4 13 A08 (?? Output 0)
09 C6 (09)                             D7 12 A09 (?? Output 0)
10 C7 (10)                             D6 11 A10 (?? Output 0)
23 D3 (?? No response)        D4 22 A11 (?? Output 0)
+5V 
GND 
RST  

Stuff in brackets confirmed pins applied 2.64V with the 10K Pot to the analog pins. 7.09KOhm~

ttgo-poe-001.yaml (ESPHome)

# Define I2C device
i2c:
  id: i2c_component
  sda: 14
  scl: 16
  scan: true

# Define the port expander hub, here we define one with id 'expander1',
# but you can define many
custom_component:
  - id: expander1
    lambda: |-
      auto expander = new ArduinoPortExpander(i2c_component, 0x08, true);
      return {expander};
  - id: expander2
    lambda: |-
      auto expander = new ArduinoPortExpander(i2c_component, 0x09, true);
      return {expander};

# Define binary sensors, use the Arduino PIN number for digital pins.
binary_sensor:
  - platform: custom
    lambda: |-
      return {ape_binary_sensor(expander2, 0),
              ape_binary_sensor(expander2, 1),
              ape_binary_sensor(expander2, 2),
              ape_binary_sensor(expander2, 3),
              ape_binary_sensor(expander2, 4),
              ape_binary_sensor(expander2, 7),
              ape_binary_sensor(expander2, 8),
              ape_binary_sensor(expander2, 9),
              ape_binary_sensor(expander2, 10),
              ape_binary_sensor(expander2, 23),
              ape_binary_sensor(expander2, 24)
             };

    binary_sensors:
      - id: expander2_0
        name: Expander2 Digital 0
      - id: expander2_1
        name: Expander2 Digital 1
      - id: expander2_2
        name: Expander2 Digital 2
      - id: expander2_3
        name: Expander2 Digital 3
      - id: expander2_4
        name: Expander2 Digital 4
      - id: expander2_7
        name: Expander2 Digital 7
      - id: expander2_8
        name: Expander2 Digital 8
      - id: expander2_9
        name: Expander2 Digital 9
      - id: expander2_10
        name: Expander2 Digital 10
      - id: expander2_23
        name: Expander2 Digital 23
      - id: expander2_24
        name: Expander2 Digital 24

# Define analog sensors
sensor:
  - platform: custom
    lambda: |-
      return {ape_analog_input(expander2, 0),  // 0 = A0
              ape_analog_input(expander2, 1),  // 1 = A1
              ape_analog_input(expander2, 2),  // 2 = A2
              ape_analog_input(expander2, 3),  // 3 = A3
              ape_analog_input(expander2, 4),  // 4 = A4
              ape_analog_input(expander2, 5),  // 5 = A5
              ape_analog_input(expander2, 6),  // 6 = A6
              ape_analog_input(expander2, 7),  // 7 = A7
              ape_analog_input(expander2, 8),  // 8 = A8
              ape_analog_input(expander2, 9),  // 9 = A9
              ape_analog_input(expander2, 10),  // 10 = A10
              ape_analog_input(expander2, 11)  // 11 = A11
             };
    sensors:
      - name: Analog A0
        id: analog_a0
        filters:
          - throttle: 2s
      - name: Analog A1
        id: analog_a1
        filters:
          - throttle: 2s
      - name: Analog A2
        id: analog_a2
        filters:
          - throttle: 2s
      - name: Analog A3
        id: analog_a3
        filters:
          - throttle: 2s
      - name: Analog A4
        id: analog_a4
        filters:
          - throttle: 2s
      - name: Analog A5
        id: analog_a5
        filters:
          - throttle: 2s
      - name: Analog A6
        id: analog_a6
        filters:
          - throttle: 2s
      - name: Analog A7
        id: analog_a7
        filters:
          - throttle: 2s
      - name: Analog A8
        id: analog_a8
        filters:
          - throttle: 2s
      - name: Analog A9
        id: analog_a9
        filters:
          - throttle: 2s
      - name: Analog A10
        id: analog_a10
        filters:
          - throttle: 2s
      - name: Analog A11
        id: analog_a11
        filters:
          - throttle: 2s
NonaSuomy commented 1 year ago

I'm not really sure what I'm doing but I got more than 0's by playing with the binary values. In the new Arduino IDE 2.0 I could hover over the pin values and then it would show me the correct pin values:

//A11 22 0x16 10110;
//A0 21 0x15 10101;
//A1 20 0x14 10100;
//A2 19 0x13 10011;
//A3 18 0x12 10010;
//A4 17 0x11 10001;
//A5 16 0x10 10000;
//A6 15 0xf 1111;
//A7 14 0xe 1110;
//A8 13 0xd 1101;
//A9 12 0xc 1100;
//A10 10 0xa 1010;

The values are dumping all over the place now so I'm sure I'm messing up the way it processes the analog values now with its bitwise operation.

Only pin F5 connected:

[01:52:11][D][sensor:127]: 'Analog A0': Sending state 32.00000  with 0 decimals of accuracy
[01:52:12][D][sensor:127]: 'Analog A1': Sending state 32.00000  with 0 decimals of accuracy
[01:52:12][D][sensor:127]: 'Analog A2': Sending state 32.00000  with 0 decimals of accuracy
[01:52:12][D][sensor:127]: 'Analog A3': Sending state 32.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A4': Sending state 1023.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A5': Sending state 977.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A6': Sending state 1023.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A7': Sending state 1023.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A8': Sending state 943.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A9': Sending state 896.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A10': Sending state 894.00000  with 0 decimals of accuracy
[01:52:13][D][sensor:127]: 'Analog A11': Sending state 848.00000  with 0 decimals of accuracy

No pins connected:

[01:54:02][D][sensor:127]: 'Analog A0': Sending state 32.00000  with 0 decimals of accuracy
[01:54:03][D][sensor:127]: 'Analog A1': Sending state 32.00000  with 0 decimals of accuracy
[01:54:03][D][sensor:127]: 'Analog A2': Sending state 32.00000  with 0 decimals of accuracy
[01:54:03][D][sensor:127]: 'Analog A3': Sending state 32.00000  with 0 decimals of accuracy
[01:54:03][D][sensor:127]: 'Analog A4': Sending state 32.00000  with 0 decimals of accuracy
[01:54:04][D][sensor:127]: 'Analog A5': Sending state 143.00000  with 0 decimals of accuracy
[01:54:04][D][sensor:127]: 'Analog A6': Sending state 159.00000  with 0 decimals of accuracy
[01:54:04][D][sensor:127]: 'Analog A7': Sending state 150.00000  with 0 decimals of accuracy
[01:54:04][D][sensor:127]: 'Analog A8': Sending state 146.00000  with 0 decimals of accuracy
[01:54:04][D][sensor:127]: 'Analog A9': Sending state 32.00000  with 0 decimals of accuracy
[01:54:04][D][sensor:127]: 'Analog A10': Sending state 151.00000  with 0 decimals of accuracy
[01:54:04][D][sensor:127]: 'Analog A11': Sending state 146.00000  with 0 decimals of accuracy

Full code

/*
Ports:
    0 0 .. 13 13
    A0: 14, A1: 15, A2: 16, A3: 17: A4: 18: A5: 19: A6: 20, A7: 21
    port bits: 5 ... 0..32
    0:   0: 00000
    1:   1: 00001
    A7: 21: 10101
*/

#include <Arduino.h>
#include <Wire.h>

//#define DEBUG 1 // remove debug so pin 0 and 1 can be used for IO
//#define DEBUG_READ 1
#define I2C_ADDRESS 9

void onRequest();
void onReceive(int);

void setup()
{
#ifdef DEBUG
  Serial.begin(115200);
  Serial.println(F("Init "));
#endif

  analogReference(INTERNAL);

  Wire.begin(I2C_ADDRESS);
  Wire.onRequest(onRequest);
  Wire.onReceive(onReceive);

#ifdef DEBUG
  Serial.println(F("Wire ok"));
#endif
}

void loop()
{
  //int temp = analogRead(A1);
  //Serial.println(temp);
}

volatile byte buffer[3];
volatile byte len = 1;

#define DIGITAL_READ(b, pin, mask) \
  if (digitalRead(pin))            \
    buffer[b] |= mask;

void readDigital()
{
  len = 3;
  buffer[0] = 0;
  DIGITAL_READ(0, PIN_B0, 1);  // Digital
  DIGITAL_READ(0, PIN_B1, 2);  // Digital
  DIGITAL_READ(0, PIN_B2, 4);  // Digital
  DIGITAL_READ(0, PIN_B3, 8);  // Digital
  DIGITAL_READ(0, PIN_B7, 16); // Digital
  DIGITAL_READ(0, PIN_E6, 32); // Digital

  //I2C Teensy 2.0
  //DIGITAL_READ(0, PIN_D0, 32); // Digital
  //DIGITAL_READ(0, PIN_D1, 64); // Digital

  DIGITAL_READ(0, PIN_D2, 128);  // Digital

  buffer[1] = 0;
  DIGITAL_READ(1, PIN_D3, 1);   // Digital
  DIGITAL_READ(1, PIN_C6, 2);   // Digital
  DIGITAL_READ(1, PIN_C7, 4);   // Digital
  DIGITAL_READ(1, PIN_D6, 8);   // Analog
  DIGITAL_READ(1, PIN_D7, 16);  // Analog
  DIGITAL_READ(1, PIN_B4, 32);  // Analog
  DIGITAL_READ(1, PIN_B5, 64);  // Analog
  DIGITAL_READ(1, PIN_B6, 128); // Analog

  buffer[2] = 0;
  DIGITAL_READ(2, PIN_F7, 1); // Analog
  DIGITAL_READ(2, PIN_F6, 2); // Analog

// I2C
  DIGITAL_READ(2, PIN_F5, 4); // Analog
  DIGITAL_READ(2, PIN_F4, 8); // Analog

  DIGITAL_READ(2, PIN_F1, 16); // Analog
  DIGITAL_READ(2, PIN_F0, 32); // Analog
  DIGITAL_READ(2, PIN_D4, 64); // Analog
  DIGITAL_READ(2, PIN_D5, 128); // Digital

//A11 22 0x16 10110;
//A0 21 0x15 10101;
//A1 20 0x14 10100;
//A2 19 0x13 10011;
//A3 18 0x12 10010;
//A4 17 0x11 10001;
//A5 16 0x10 10000;
//A6 15 0xf 1111;
//A7 14 0xe 1110;
//A8 13 0xd 1101;
//A9 12 0xc 1100;
//A10 10 0xa 1010;

  //buffer[3] = 0;
  //DIGITAL_READ(3, PIN_E6, 1);

// DIGITAL READ not supports on A3 .. A7
#ifdef DEBUG_READ
  Serial.print(F("Read 3 bytes: "));
  Serial.print(buffer[0]);
  Serial.print(' ');
  Serial.print(buffer[1]);
  Serial.print(' ');
  Serial.println(buffer[2]);

#endif
}
void readAnalog(int pin)
{
  int val = analogRead(A9 + pin);
  len = 2;
  buffer[0] = val & 0xFF;
  buffer[1] = (val >> 8) & 0b11;
#ifdef DEBUG_READ
  Serial.print(F("Read analog pin "));
  Serial.println(pin);
#endif
}

void onRequest()
{
  Wire.write(const_cast<uint8_t *>(buffer), len);
}

#define CMD_DIGITAL_READ 0x0

#define CMD_WRITE_ANALOG 0x2
#define CMD_WRITE_DIGITAL_HIGH 0x3
#define CMD_WRITE_DIGITAL_LOW 0x4

#define CMD_SETUP_PIN_OUTPUT 0x5
#define CMD_SETUP_PIN_INPUT_PULLUP 0x6
#define CMD_SETUP_PIN_INPUT 0x7

// 8 analog registers.. A0 to A7
// A4 and A5 not supported due to I2C
#define CMD_ANALOG_READ_A9 0b1100 // 0x8
// ....
#define CMD_ANALOG_READ_A0 0b10101 // 0xF

#define CMD_SETUP_ANALOG_INTERNAL 0x10
#define CMD_SETUP_ANALOG_DEFAULT 0x11

void onReceive(int numBytes)
{
#ifdef DEBUG_READ
  Serial.print("Received bytes: ");
  Serial.println(numBytes);
#endif
  int cmd = Wire.read();

  switch (cmd)
  {
  case CMD_DIGITAL_READ:
    readDigital();
    break;
  }

  if (cmd >= CMD_ANALOG_READ_A9 && cmd <= CMD_ANALOG_READ_A0)
  {
    readAnalog(cmd & 0b111);
    return;
  }

  int pin = Wire.read();

  switch (cmd)
  {
  case CMD_WRITE_DIGITAL_HIGH:
  case CMD_WRITE_DIGITAL_LOW:
  {
    bool output = cmd == CMD_WRITE_DIGITAL_HIGH;
    digitalWrite(pin, output);
#ifdef DEBUG
    Serial.print(F("Pin "));
    Serial.print(pin);
    Serial.println(output ? F(" HIGH") : F(" LOW"));
#endif
    break;
  }
  case CMD_WRITE_ANALOG:
  {
    int val = Wire.read() & (Wire.read() << 8);
    analogWrite(pin, val);
#ifdef DEBUG
    Serial.print(F("Pin "));
    Serial.print(pin);
    Serial.print(F(" Analog write "));
    Serial.println(val);
#endif
    break;
  }
  case CMD_SETUP_PIN_OUTPUT:
    pinMode(pin, OUTPUT);
#ifdef DEBUG
    Serial.print(F("Pin "));
    Serial.print(pin);
    Serial.println(F(" OUTPUT"));
#endif
    break;
  case CMD_SETUP_PIN_INPUT:
    pinMode(pin, INPUT);
#ifdef DEBUG
    Serial.print(F("Pin "));
    Serial.print(pin);
    Serial.println(F("INPUT"));
#endif
    break;
  case CMD_SETUP_PIN_INPUT_PULLUP:
    pinMode(pin, INPUT_PULLUP);
#ifdef DEBUG
    Serial.print(F("Pin "));
    Serial.print(pin);
    Serial.println(F("INPUT PULLUP"));
#endif
    break;
  case CMD_SETUP_ANALOG_INTERNAL:
    analogReference(INTERNAL);
//#ifdef DEBUG
    //Serial.println(F("Analog reference INTERNAL"));
//#endif
    break;
  case CMD_SETUP_ANALOG_DEFAULT:
    analogReference(DEFAULT);
//#ifdef DEBUG
    //Serial.println(F("Analog reference DEFAULT"));
//#endif
    break;
  }
}