Hello,
is it possible to modify software serial code to make it work with inverted software signals to avoid using hardware TTL inverter?
Hello,
is it possible to modify software serial code to make it work with inverted software signals to avoid using hardware TTL inverter?
In short NO.
The serial system uses the hardware UART built into the Arduino and you can't change it.
However, you could hack the software serial library to use inverted signals although I don't know why you would want to. Where do you need a TTL inverter?
You can modify the software serial code, yes. But note that a typical TTL-to-RS232 circuit not only inverts the signal, but also converts it from a 0-5V level into -12V to +12V. The serial receiver does the opposite, it converts an incoming -12V to +12V signal into 0-5V. A TTL circuit, or the Arduino, will be damaged if it is connected directly to an RS-232 signal.
I'm interfacing Garmin GPS25-LVC and it talks in "TTL" levels, but unfortunatelly inverted. I ran into a lot of trouble before i learnt that pins 1 and 2 used for UART are also used by development environment console. So i'm thinking i would modify GPS EM-406 example to negate the bits and pins where i think is appropriate. Somehow it didn't quite work from the first time, though i'm sure i just did something wrong in the code and just wanted to confirm that tecnically it should be possible to do?
#include <ctype.h>
#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94
byte rx = 6; // Garmin GPS25-LVS tx line connected to pin 6 on Arduino (4800baud)
byte SWval;
char line[80]="";
void setup() {
pinMode(rx,INPUT);
digitalWrite(13,HIGH); // turn on debugging LED
Serial.begin(4800); // Setup USB serial port monitor to 4800baud
}
int SWread()
{
byte val = 0;
while (! digitalRead(rx)); // this might be the problem - negating 1 will not give 0
//wait for start bit
if (digitalRead(rx) == HIGH) {
delayMicroseconds(halfBit4800Delay);
for (int offset = 0; offset < 8; offset++) {
delayMicroseconds(bit4800Delay);
val |= digitalRead(rx) << offset;
}
//wait for stop bit + extra
delayMicroseconds(bit4800Delay);
delayMicroseconds(bit4800Delay);
return val ^ 0xFF;
}
}
void getLine()
{
int i = 0;
line[0] = SWread();
if (line[0] == 36) //string starts with $
{
i++;
line[i] = SWread();
while(line[i] != 13 & i<80) //carriage return or max size
{
i++;
line[i] = SWread();
}
line[i+1] = 0; //make end to string
}
} // end getLine()
void loop()
{
SWval = SWread();
Serial.print(SWval);
}
I'm interfacing Garmin GPS25-LVC and it talks in "TTL" levels, but unfortunatelly inverted.
All TTL level serial signals are inverted, it's the convention! TTL-to-RS232 buffer chips invert the signal. It's not unfortunate, in the case of your GPS, it's done that way by design to be compatible with existing hardware. So presumably, software serial code generates and accepts inverted serial signals? Otherwise, software serial wouldn't work with (inverting) TTL-to-RS232 buffer chips.
I was sure somebody would have thought of doing the software version of inverter for RS232 TTL signals. Surprisingly I can't find code example of inverted RS232 communication. adding TTL-to-RS232 would solve the problem but i want to stay with TTL levels.
A little off topic perhaps, but I've always wondered if the control lines (DTR, RTS, etc.) are also inverted between Rs232 and TTL serial. ?
A little off topic perhaps, but I've always wondered if the control lines (DTR, RTS, etc.) are also inverted between Rs232 and TTL serial. ?
I don't believe so. The RS-232 is not consistent on logic (voltage)polarity sense between the data lines and the control lines.
Data is inverted:
Mark = high = on data bit = stop bit = -12vdc
Space = low = off data bit = start bit = +12vdc
Control lines (like DTR) are NOT inverted:
signal on = high = signal asserted = +12vdc
signal off = low = signal not asserted = = -12vdc
So one can see where the originating source of the confusion comes from and why there are all the hoops that software and interface hardware have to jump through.
Lefty
Thanks Lefty,
That confirms why I struggled a few extra days when I was working on this.
Here is working code if anybody is interested. The only problem is high bit which i had to nullify, the code this was based on (without inversion) seem to have had the same problem (someone complained). luckely this bit is not important for NMEA strings.
#include <ctype.h>
#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94
byte rx = 5; // GPS 25LVC tx line connected to pin 5 on Arduino (4800baud)
byte SWval;
char line[80]="";
void setup() {
pinMode(rx,INPUT);
digitalWrite(13,HIGH); // turn on debugging LED
Serial.begin(9600); // Setup USB serial port monitor to 4800baud
}
int SWread()
{
byte val = 0;
while (digitalRead(rx) == LOW);
//wait for start bit
if (digitalRead(rx) == HIGH) {
delayMicroseconds(halfBit4800Delay);
for (int offset = 0; offset < 8; offset++) {
delayMicroseconds(bit4800Delay);
val |= (digitalRead(rx) == LOW) << offset;
}
//wait for stop bit + extra
delayMicroseconds(bit4800Delay);
delayMicroseconds(bit4800Delay);
return val & 0x7F; // for some reason high bit doesn't come out correctly
}
}
void getLine()
{
int i = 0;
line[0] = SWread();
if (line[0] == 36) //string starts with $
{
i++;
line[i] = SWread();
while(line[i] != 13 & i<80) //carriage return or max size
{
i++;
line[i] = SWread();
}
line[i+1] = 0; //make end to string
}
} // end getLine()
void loop()
{
SWval = SWread();
Serial.print(SWval);
}