I2C to RS232

Following the information in SC16IS752 and in MAX232, I'm attempting to make 2 Arduinos communicate with each other over RS232 (because of the distance it can get compared to other protocols) and using the I2C to 2 UART so that several UARTs can exist at the same time.

I've attached the schematic I've used for each side.

In addition, I've tried just getting the SC chip to talk to another and had success, and I've had an Atmega328p using the MAX232 on its hardware serial port talking to a desktop. Neither of these were a problem, but when trying to get 2 Arduinos communicating over the I2C to RS232 or even just getting one Arduino to talk to a desktop, it doesn't work.

In the next post I'll upload the code for the Arduino.
When the Arduino communicates to the computer, I see 0xFF on the computer side and 0x00 on the Arduino side.

#include <SC16IS752.h>
#include <AltSoftSerial.h>
#include <SPI.h>
#include <Wire.h>
// -----!!!!! COM13 --------
// https://stackoverflow.com/questions/42151118/how-to-override-define-in-arduino-library-header
#ifdef SC16IS750_CRYSTCAL_FREQ //if the macro (16000000UL) is defined 
#undef SC16IS750_CRYSTCAL_FREQ //un-define it
#define SC16IS750_CRYSTCAL_FREQ (16000000UL)//redefine it with the new value
#endif 

#undef SC16IS750_DEBUG_PRINT //un-define it

// https://github.com/nopnop2002/SC16IS752
SC16IS752 i2cuart = SC16IS752(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA);

// AltSoftSerial always uses these pins:
//
// Board          Transmit  Receive   PWM Unusable
// -----          --------  -------   ------------
// Arduino Uno        9         8         10

bool isSCChipMode = true;
AltSoftSerial altSerial;

void setup() {
  // put your setup code here, to run once: 
  Serial.begin(9600);
  
  if(isSCChipMode){
    Serial.println("Start SC16I testing");
    // UART to Serial Bridge Initialization
    i2cuart.begin(SC16IS752_DEFAULT_SPEED, SC16IS752_DEFAULT_SPEED); //baudrate setting
    if (i2cuart.ping()!=1) {
        Serial.println("Device not found");
        while(1);
    } else {
        Serial.println("Device found");
    }
    Serial.println("Start serial communication");
    Serial.print("frequency: ");
    Serial.println(SC16IS750_CRYSTCAL_FREQ);
  } else {
    Serial.println("Start MAX 232 testing");
    altSerial.begin(9600);
  }
}

void writelnToI2C(char msg[]){
  Serial.print("----------Begining write msg len =");
  Serial.println(strlen(msg));
  for(int i = 0; i < strlen(msg); i++){
    i2cuart.write(SC16IS752_CHANNEL_B, msg[i]);  
  }
  i2cuart.write(SC16IS752_CHANNEL_B, 0x0A);
  i2cuart.flush(SC16IS752_CHANNEL_B);
  Serial.println("-----------------End write msg");
}

int i2cBuffer;
char i2cChar;

void i2cReadAvailable(){
  Serial.println("----------Begining Read------------------");
  int charCountToRead = i2cuart.available(SC16IS752_CHANNEL_B);
  Serial.print("chars to read from Arduino A: ");
  Serial.println(charCountToRead);
  do {
    for(int i = 0; i < charCountToRead; i++){
      i2cBuffer = i2cuart.read(SC16IS752_CHANNEL_B);
      i2cChar = i2cBuffer;
      Serial.print("i2cBuffer:= ");
      Serial.print(i2cChar);
      Serial.print(" Hex: = ");
      Serial.println(i2cBuffer, HEX);
    }

    charCountToRead = i2cuart.available(SC16IS752_CHANNEL_B);

    Serial.print("chars to read from Arduino A: ");
    Serial.println(charCountToRead);
  } while (charCountToRead != 0);

  Serial.println();  
  Serial.println("----------End read----------");
}

void processI2C(){
  char data[] = "hello there I'm com13";
  writelnToI2C(data);
  i2cReadAvailable();
}

void processAltSoftSerialMax232(){
  char c;
  Serial.println("-----End Reading MAX232");
  while(altSerial.available()){
    Serial.print(c);
  }
  Serial.println("------Done Reading MAX232");
}

unsigned long lastMillis;
int seconds = 12;

void loop() {
  //altSerial.println("hello there I'm com13");
  if (millis() - lastMillis >= seconds * 1000UL){
    if(isSCChipMode){
      Serial.println("processI2C");
      processI2C();  
    } else {
      Serial.println("process max232");
      altSerial.println("hello there I'm com13");
      processAltSoftSerialMax232();
    }
    
    lastMillis = millis();  
  }
}

I used SC chip library for the #include <SC16IS752.h> and how to use it.

In the datasheet of the SC16IS752, it says that its pins are 5V tolerant. Then it is okay to connect its SDA and SCL pins to the ATmega328P.
I assume that the SC16IS752 is working, so you don't have to test that.
A logic analyzer would help. I'm very fond of the 30 dollar LHT00SU1 with sigrok/PulseView.

Do you use the SPI bus ? If not, please remove this line: #include <SPI.h>

I'm confused when I try to read the sketch. I think the millis-timer and the way the data is flowing is not okay.
For example this:

while(altSerial.available()){
  Serial.print(c);
}

The normal way is to always check incoming data, and only now and then transmit something.
Can you make a drawing how everything is connected and how the data flows in the sketch ? The problem seems to be the structure of the sketch. Maybe you should start all over.
You should start with the most simple test sketch.
The body of the loop() should check all the things, and act if something was received or if a timer is ready.

void loop()
{
  check if something is received via Serial

  check if something is received via AltSerial

  check if something is received via I2Cuart

  check a millis-timer

  check another millis-timer
 
  check yet another millis-timer
}

You do not show a common ground between the SC16IS752 and MAX232 but RS232 voltage levels are with reference to a common ground.

countrypaul:
You do not show a common ground between the SC16IS752 and MAX232 but RS232 voltage levels are with reference to a common ground.

Everything that says GND in the schematic is connected together. I double checked it just to be sure.

Here's the simplified code

#include <SC16IS752.h>
// -----!!!!! COM13 --------
// https://stackoverflow.com/questions/42151118/how-to-override-define-in-arduino-library-header
#ifdef SC16IS750_CRYSTCAL_FREQ //if the macro (16000000UL) is defined 
#undef SC16IS750_CRYSTCAL_FREQ //un-define it
#define SC16IS750_CRYSTCAL_FREQ (16000000UL)//redefine it with the new value
#endif 

#undef SC16IS750_DEBUG_PRINT //un-define it

// https://github.com/nopnop2002/SC16IS752
SC16IS752 i2cuart = SC16IS752(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA);

void setup() {
  // put your setup code here, to run once: 
  Serial.begin(9600);
  
  Serial.println("Start SC16I testing");
  // UART to Serial Bridge Initialization
  i2cuart.begin(SC16IS752_DEFAULT_SPEED, SC16IS752_DEFAULT_SPEED); //baudrate setting
  if (i2cuart.ping()!=1) {
      Serial.println("Device not found");
      while(1);
  } else {
      Serial.println("Device found");
  }
  Serial.println("Start serial communication");
  Serial.print("frequency: ");
  Serial.println(SC16IS750_CRYSTCAL_FREQ);
}

void writelnToI2C(char msg[]){
  Serial.print("----------Begining write msg len =");
  Serial.println(strlen(msg));
  for(int i = 0; i < strlen(msg); i++){
    i2cuart.write(SC16IS752_CHANNEL_B, msg[i]);  
  }
  i2cuart.write(SC16IS752_CHANNEL_B, 0x0A);
  i2cuart.flush(SC16IS752_CHANNEL_B);
  Serial.println("-----------------End write msg");
}

int i2cBuffer;
char i2cChar;

void i2cReadAvailable(){
  Serial.println("----------Begining Read------------------");
  int charCountToRead = i2cuart.available(SC16IS752_CHANNEL_B);
  Serial.println(charCountToRead);
  do {
    for(int i = 0; i < charCountToRead; i++){
      i2cBuffer = i2cuart.read(SC16IS752_CHANNEL_B);
      i2cChar = i2cBuffer;
      Serial.print("i2cBuffer:= ");
      Serial.print(i2cChar);
      Serial.print(" Hex: = ");
      Serial.println(i2cBuffer, HEX);
    }

    charCountToRead = i2cuart.available(SC16IS752_CHANNEL_B);

    Serial.print("chars to read from Arduino A: ");
    Serial.println(charCountToRead);
  } while (charCountToRead != 0);

  Serial.println("\n----------End read----------");
}

unsigned long lastMillis;
int seconds = 10;

void loop() {
  if (millis() - lastMillis >= seconds * 1000UL){
    Serial.println("processI2C");
    char data[] = "hello there I'm com13";
    writelnToI2C(data);
    i2cReadAvailable();
    lastMillis = millis();  
  }
}

What is wrong with checking it every so often?

I attached a flow chart to show what I'm wanting.

I2C to ttl to rs232 flow.png

I2C to ttl to rs232 flow.png

abs0:
What is wrong with checking it every so often?

A buffer could be empty, or (almost) full. Because that is unknown, it is better to read it as fast as possible. With multiple data inputs, it is even more important to check everything. It costs almost no time.

void loop()
{
  if( Serial.avaiable() > 0) 
  {
    ...
  }
}

In case the other device only returns data after sending a command to it, then it might be possible to read the reply after sending the command. Personally, I prefer to check the input all the time in that situation as well.

Can you try a pass-through sketch ?
Connect the MAX232 to a computer and run a terminal program for that serial port.
Connect the Arduino IDE to the Arduino and open the serial monitor.
Try to send text in both directions.

void loop()
{
  if( Serial.available() > 0)
  {
    int inChar = Serial.read();
    i2cuart.write( SC16IS752_CHANNEL_B, inChar); 
  }

  if( i2cuart.available( SC16IS752_CHANNEL_B) > 0)
  {
    int inChar = i2cuart.read( SC16IS752_CHANNEL_B);
    Serial.write( inChar);
  }
}

The thing is, when I try the SC16IS752 where I connect its TX and RX together, a loop, I get the information in that I pushed out, but when I try to connect 2 of them together, I get nothing on one side and garbage (usually values that aren't in the 7bit ASCII table).

Just as an update, I got the two SC16IS752 chips to talk to each other by lowering the baud rate to 1200. I'm using breadboards btw.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.