Go Down

Topic: serial on different pins than 0 or 1 (Read 4128 times) previous topic - next topic

tof

Hi, is it easy to implement serial communication on pins other than 0 or 1.
I do not need to have 2 simultaneous serial connections, I would like to use pins 11 and 12 instead (as they are linked with the ICSP connector and provide an easy way to connect external devices.

Tom
Thomas Ouellet Fredericks

mellis

It's not so easy: there are plenty of libraries that provide a software serial port on any pins, but all the ones I've seen require the use of hardware timers, which on Arduino are already used (for millis() and PWM generation).  Could you try something hacky like configuring pins 11 and 12 as input and connecting them to pins 0 and 1?  

We've managed to put together a function to send serial data out, but not yet one that receives it.  Here's the serial out code, which should work at 9600 and 19200 baud, at least:

Code: [Select]

#define BAUDRATE 9600

int tx = 7;

// function that puts a byte of data to software serial port
void serout(int txPin, byte data)
{
 int bitDelay = 1000000 / BAUDRATE - 25;
 byte i = 0;
 byte mask;

 digitalWrite(txPin, LOW);
 delayMicroseconds(bitDelay);

 for (mask = 0x01; mask; mask <<= 1) {
   if (data & mask){ // choose bit
     digitalWrite(txPin,HIGH); // send 1
   }
   else{
     digitalWrite(txPin,LOW); // send 1
   }
   delayMicroseconds(bitDelay);
 }

 digitalWrite(txPin, HIGH);
 delayMicroseconds(bitDelay);
}

void setup() {
 pinMode(tx,OUTPUT);
}

void loop() {
 serout(tx,'h');
 serout(tx,'e');
 serout(tx,'l');
 serout(tx,'l');
 serout(tx,'o');
 delay(1000);
}

Antonio

Hi everybody,

I have the same question as Tof, but in my case, I need to have 2 simultaneous serial connections. The previous code can help me to send data on a second serial line, but there is still the problem to receive data on the second serial connection.
Mellis, you talked about libraries that provide a software serial, as far as there is an unused hardware timer. Is it possible to add a second timer to Arduino (for example on an digital pin) and then use it for the software serial?

Antonio

mellis

It's probably easier to try to get a purely software serial (i.e. no hardware timers) working.  Here's some code that tries to do, but doesn't quite work.  

The fudge variable is used to slightly adjust the delay between bits for each byte read - an attempt to get the timing exactly right.  

Code: [Select]

#define BAUDRATE 9600

// the width of a single bit of serial data in microseconds
// in each second (1000000 microseconds) there are a number of bits equal
// to the baud rate (e.g. 9600), so each bit lasts for 1000000 / baudrate
// microseconds
int width = 1000000 / BAUDRATE;
int fudge = 20;
int val = 0;
int count = 0;

int rx = 6;

void setup() {
 pinMode(rx,INPUT);
 digitalWrite(13,HIGH);
 beginSerial(BAUDRATE);
}

void loop() {
 int offset;
 boolean error = true;

 // one byte of serial data (LSB first)
 // ...--\    /--\/--\/--\/--\/--\/--\/--\/--\/--...
 //       \--/\--/\--/\--/\--/\--/\--/\--/\--/
 //      start  0   1   2   3   4   5   6   7 stop

 while (digitalRead(rx));

 // frame start indicated by a falling edge and low start bit
 // jump to middle of start bit
 //delayMicroseconds(width / 2 + fudge);

 // confirm that this is a real start bit, not line noise
 //if (digitalRead(rx) == LOW) {

   for (offset = 0; offset < 8; offset++) {
     // jump to middle of next bit
     delayMicroseconds(width + fudge);
     val |= digitalRead(rx) << offset;
   }

   // check stop bit is high
   delayMicroseconds(width + fudge);
   if (digitalRead(rx) == HIGH) {
     error = false;
   }
   serialWrite(val);
   count++;
   if (count % 2 == 0) {
     fudge--;
     serialWrite(width + fudge);
   }
 //}
}

fallen

Hi ! mellis , I also very want the  software serial  too, can I use the codes you gived together ? (I means full duplex)

and about the hardware timers , I know a timer IC called :"555" , and there is a software(English) help people to use it , you can download : http://fallen11.googlepages.com/555timer_install.rar
but I don't have experience to programme a software serial  use this IC , if you have some codes or examples about let Arduino work with it , please help us , thank you !

Antonio

Finally, Fabrice and I got something quite interesting. The previous code for software Rx didn't work for us. So we changed some things (don't ask us why it works now, we don't really know ...).

______                                      _________                ______
|         |         __________          |               |              |          |
| PC1  |-------|  MAX233  |--------|  Arduino  |-----------|  PC2  |
|_____|         |_________|          |________|              |______|

Our PC1 serial Tx is connected on our new software Rx (pin 6) through a MAX233 (to switch from RS232 to TTL). Arduino is connected to PC2 with the classical hardware serial link.
When I type a text in a hyperterminal on PC1, it is received by Arduino and sent back on PC2 hyperterminal.

It works for a typed text, but not yet by sending a text file.  

Here is the modified software Rx code:

Code: [Select]
#define BAUDRATE 9600

// the width of a single bit of serial data in microseconds
// in each second (1000000 microseconds) there are a number of bits equal
// to the baud rate (e.g. 9600), so each bit lasts for 1000000 / baudrate
// microseconds
int width = 1000000 / BAUDRATE;
int fudge = -25;
unsigned int val = 0;
int count = 0;
int state = 0;

int rx = 6;

void setup() {
 pinMode(rx,INPUT);
 digitalWrite(13,HIGH);
 beginSerial(BAUDRATE);
}

void loop() {
 int offset;
 boolean error = true;

 // one byte of serial data (LSB first)
 // ...--\    /--\/--\/--\/--\/--\/--\/--\/--\/--...
 //       \--/\--/\--/\--/\--/\--/\--/\--/\--/
 //      start  0   1   2   3   4   5   6   7 stop

 while (digitalRead(rx));

 // frame start indicated by a falling edge and low start bit
 // jump to middle of start bit
 //delayMicroseconds(width / 2 + fudge);

 // confirm that this is a real start bit, not line noise
 if (digitalRead(rx) == LOW) {
   delayMicroseconds(width/2);
   
   for (offset = -1; offset < 8; offset++) {
     // jump to middle of next bit
       val |= (digitalRead(rx) << offset);
     delayMicroseconds(width + fudge);
   }

   // check stop bit is high
   delayMicroseconds(width + fudge);
   if (digitalRead(rx) == HIGH) {
     error = false;
   }

   Serial.print(val,BYTE);
   val = 0;

 }
}


It seems to be very sensitive to time delay. As soon as you add some code, the pin value can be sampled at a wrong instant.

Antonio

mellis

Very cool!  We've been trying to get this working for a long time.

By using a faster baud rate to send data back to the computer from the Arduino board, I was able to almost handle file transfers.  I also cleaned up the code a bit.  Here it is:

Code: [Select]

#define BAUDRATE 9600

// the width of a single bit of serial data in microseconds
// in each second (1000000 microseconds) there are a number of bits equal
// to the baud rate (e.g. 9600), so each bit lasts for 1000000 / baudrate
// microseconds
int width = 1000000 / BAUDRATE;
int fudge = -25;
int rx = 6;

void setup() {
 Serial.begin(115200);
 pinMode(rx,INPUT);
 digitalWrite(13,HIGH);
}

void loop() {
 int val = 0;
 
 // one byte of serial data (LSB first)
 // ...--\    /--\/--\/--\/--\/--\/--\/--\/--\/--...
 //       \--/\--/\--/\--/\--/\--/\--/\--/\--/
 //      start  0   1   2   3   4   5   6   7 stop

 while (digitalRead(rx));

 // confirm that this is a real start bit, not line noise
 if (digitalRead(rx) == LOW) {
   // frame start indicated by a falling edge and low start bit
   // jump to the middle of the low start bit
   delayMicroseconds(width / 2);
   
   // offset of the bit in the byte: from 0 (LSB) to 7 (MSB)
   for (int offset = 0; offset < 8; offset++) {
     // jump to middle of next bit
     delayMicroseconds(width + fudge);
     
     // read bit
     val |= digitalRead(rx) << offset;
   }
   
   delayMicroseconds(width + fudge);

   Serial.print(val, BYTE);
   
   val = 0;
 }
}

tof

There are probably hardware solutions that could be more effective:
http://www.acroname.com/robotics/info/ideas/sermux/sermux.html

Or even more promising, check the circuit on page 10c.3 of:
http://www.ece.utexas.edu/~valvano/metrowerks/Lab10c.pdf

One master device, many slaves.

Tom
Thomas Ouellet Fredericks

I want to be able to transmit data on an RS-485 interface using the Arduino. Will the MAX2232 chip work or should I use something else?

BlackDragon

How do you even transmit data out of a pin? i cannot get anything to work. when i think i am transmitting, i can unplug the usb cord and get errors. I have a Duemilanove and tried serial.write  , digitalWrite and got nothing. Any help would be greatly appreciated.

Thank you

mem

See the first post in this thread : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1233298805

This has a link to NewSoftSerial, a library tha enables you to send (and receiver) on any data pin

Go Up