Making ASR33 Serial at 110 baud to run on Adruino

I have been trying to figure out a good project to use Ardrino to do a little demo on my ASR33.

It turns out to be a tough job.

I already have the electrical conversion done. My ASR33 Teletype is set up to receive RS232. I also have the TTL to RS232 converter working.

The problem I have is that Arduino cannot do 110 baud. Therefore, I need to bitbash some sort of software serial to allow me to send a string of characters to the Teletype.

Believe me, if you have ever seen one of these machines print, you would be as hot to make this work as I am.

My ASR33 is about 50 years old. It works fine, because I can do a hardware loop back and it prints what I send. That's a good thing.

Now, I am a new guy to all of this Arduino stuff. I know the Arduino cannot do 110 baud without serious modifications. I have been looking at the serial stream output on my scope and as soon as I go from 300 to 110 baud, the data word get shorter rather than longer. Arduino just doesn't support anything less than 300.

I found this code that someone wrote for an eariler teletype that should help me think this through. There are some notes in it that I have made but I am confused about a few things. It was originally set for 50 baud for earlier teletype machines that had 5 bits, 1 start and 1.5 stop bits 50 N51.5. Don't ask me what 1.5 stop bits is. I think it is really 2 stop bits but the last stop must be leading edge triggered.

Teletype ASR33 were 8 bit Ascii machines. 110 N82 I think is the protocol. I think the ASR33 doesn't pay any attention to the 8th bit.

Here is where I need help. I understand a large amount of this code but some stuff I fall short on.

  1. Where do I put the data I want to be printed on the Teletype. I think that variable is missing.
  2. What are "rtty2 and rtty1"? I am thinking they are just a couple of LEDs to show how this is working.

There are a couple of delays that I think add up to the bit time of 110 baud. I have already tried to modify them . I think .00909 = 9ms + 90us delay(9) should be the delay time for 110 baud. Remember that my serial word length is 11 bits rather than the normal 10 bits with most baud rates. Its 10 characters per second but each character is 11 bits.

/*  I want a simple Arduino Sketch to generate bitbashed 110 N82 serial to run my
 *   ASR33 Teletype.
 *   I would like it to print something simple like:
 *   " The quick brown fox jumps over the lazy dogs back 1 2 3 4 5 6 7 8 9 10 "
 *   
 *   
 *   
 *   Transmitted string is broken into each byte (character) with rtty_txstring and each byte
  into its corresponding bits with rtty_txbyte. The bits are then written out to Arduino pins
  with rtty_txbit.
*/

void rtty_txstring (char *string)              // *variable is a pointer to the variable
{

  /* Simple function to send a char at a time to
   ** rtty_txbyte function.
   ** Each char is one byte (8 Bits)
  */

  char c;

  c = *string++;

  while ( c != '\0')             // \0 denotes end of string
  {
    rtty_txbyte (c);
    c = *string++;               //move to c to next char of string
  }
}


void rtty_txbyte (char c)
{

  /* Simple function to sent each bit of a char tortty_txbit function.
     The bits are sent Least Significant Bit first
     All chars should be preceded with a 0 and proceded with a 1. 0 = Start bit; 1 = Stop bit
  */


  rtty_txbit (0);            // Start bit

  // Send bits for char LSB first

  for (int i = 0; i < 8; i++) //8 bits in char (byte).
  {
    if (c & 1) rtty_txbit(1);

    else rtty_txbit(0);

    c = c >> 1;

  }

  rtty_txbit (1);           // Stop bit
}

void rtty_txbit (int bit)
{
  if (bit)
  {
    // high

    digitalWrite(rtty1, LOW);
    digitalWrite(rtty2, HIGH);
  }
  else
  {
    // low
    digitalWrite(rtty2, LOW);
    digitalWrite(rtty1, HIGH);
  }

  //.00909 = 9ms + 90us
  delay(9); // 9 ms
  delayMicroseconds(90);  //90 us
}

So, does anyone want to take this on with me?

This is really cool stuff. I would love some help with this code.

Greg

It looks like these are just functions that you would call from your main loop() routine.

void loop() {
  rtty_txstring( "Hello World" );
}
[code]
   
rtty1 and rtty2 would be defined as pins that you are transmitting on.  Why you are transmitting on two pins, I don't know... you only need 1 pin to transmit RS232

found this link with that gave the comm specs(VintageComputer.net - Teletype 101 | How to interface a computer with a Teletype ASR 33 Model | Teletype ASR 33 | ASR 33 Teletype | ASR33 | ASR 33 TTY | current loop):
ASR 33 Communications Specs

  • Current levels for microcomputers usually 20 mA (milliAmps)
  • Transmission modes of Half and Full Duplex (full = ability to send and transmit simultaneously)
    110 baud
  • Eleven pulses per ASCII character (8 data bits, plus one start and two stop bits)
  • Receiving is independent of the sending making full duplex possible
  • Stream of serial pulses arrives at the selector magnet drive that drives the selector cams, which set the desired ASCII code in a series of code bars - totally mechanical.
  • System is designed for ASCII code mechanically, but other codes are possible.

for such a low baud rate you could always use the softwareserial library instead of that code... probably would simplify alot of that you want to do.

bearing in mind that softwareserial implements N81, to implement N82, you simply to add a delay between each character write to implement N82 protocol. (IMHO it's so slow though you could "easily" implement millis() for a non-blocking code if you have the experience for it that is! :slight_smile: )

hope that makes sense.

I don's see why you have "rtty1" AND "rtty2"; you should only need one output bit.
delayMicroseconds() will handle up to 16383 us, so there's no need to break up your 9.09ms into separate ms and us quantities.

You can simplify quite a bit by taking advantage of some boolean operators and identities...

(I've removed your comments for brevity. But they were really excellent comments compared to a lot of code that I've seen go by.)

void rtty_txbyte (char c) {
  rtty_txbit (0);            // Start bit
  for (byte i = 0; i < 8; i++) //8 bits in char (byte).
  {
    rtty_txbit(c & 1);
    c = c >> 1;
  }
  rtty_txbit (1);           // Stop bit
}

void rtty_txbit (byte bit) {
  digitalWrite(rtty1, bit);
  delayMicroseconds(9090);  //9.09 ms
}

OK -- I am getting somewhere.

I need to declare the data string properly. I don't know how to do that.

The rest of this seems to work a bit, though I don't know what character it is displaying.

This is the TTL output. It is starting with a low start bit and ending with 2 high stop bits. That is correct.

How do you like my DIY storage scope?

/* Here is a compilation of suggestions from the Forum*/

const uint8_t rtty1 = 10;  // rtty1 is the serial output and is output 10
void setup() {
  pinMode (rtty1, OUTPUT);

}

void loop() {
  rtty_txbyte( "ABCDE" );  //This is the Text I want to print
  //  rtty_txstring( "ABCDE" );  //This is the Text I want to print

  delay(200 ); // Pause for 2/10 second then loop again.

}

void rtty_txbyte (char c) {
  rtty_txbit (0);            // Start bit
  for (byte i = 0; i < 8; i++) //8 bits in char (byte).
  {
    rtty_txbit(c & 1);
    c = c >> 1;
  }
  rtty_txbit (1);           // Stop bit 1
  rtty_txbit (1);           // Stop bit 2

}

void rtty_txbit (byte bit) {
  digitalWrite(rtty1, bit);
  delayMicroseconds(9090);  //9.09 ms
}

I have a problem with the rtty_txbyte() vs rtty_txstring() With txbyte I get the above waveform rtty_txstring() errors asking for me to declare it. (help me here)

I added a 2nd stop bit and I can check the timing on my scope. I am getting that.

It keeps transmitting the same character over and over.

Greg

You're passing a string to a routine that expects a byte. On my Uno, it's emitting character 16. I thought I saw a function in your earlier code that processed a string.

wildbill:
You're passing a string to a routine that expects a byte.

Yes, I know. Thats where I need some additional help.

Greg

you didn't include the rtty_txstring() function in your final sketch...

/* Here is a compilation of suggestions from the Forum*/

const uint8_t rtty1 = 10;  // rtty1 is the serial output and is output 10
void setup() {
  pinMode (rtty1, OUTPUT);

}

void loop() {
  rtty_txbyte( "ABCDE" );  //This is the Text I want to print
  //  rtty_txstring( "ABCDE" );  //This is the Text I want to print

  delay(200 ); // Pause for 2/10 second then loop again.

}

void rtty_txbyte (char c) {
  rtty_txbit (0);            // Start bit
  for (byte i = 0; i < 8; i++) //8 bits in char (byte).
  {
    rtty_txbit(c & 1);
    c = c >> 1;
  }
  rtty_txbit (1);           // Stop bit 1
  rtty_txbit (1);           // Stop bit 2

}

void rtty_txbit (byte bit) {
  digitalWrite(rtty1, bit);
  delayMicroseconds(9090);  //9.09 ms
}

void rtty_txstring (char *string)              // *variable is a pointer to the variable
{

  /* Simple function to send a char at a time to
   ** rtty_txbyte function.
   ** Each char is one byte (8 Bits)
  */

  char c;

  c = *string++;
    while ( c != '\0')             // \0 denotes end of string
  {
    rtty_txbyte (c);
    c = *string++;               //move to c to next char of string
  }
}

Thank you --

I looks good on the scope.

I will mess around with it a bit now.

Standby for more questions!

Greg

IT WORKS!

Here is the final code:

/* Arduino Forum assisted ASR33 Demo
ASR33 Teletype is 110 Baud N82.  
*/

const uint8_t rtty1 = 10;  // rtty1 is the serial output and is output 10
void setup() {
  pinMode (rtty1, OUTPUT);

}

void loop() {

  rtty_txstring( "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOGS BACK 123456789" );  //This is the Text I want to print
  rtty_txstring("\r");  //CR
  rtty_txstring("\n");  //LF
  delay(500); // Pause to allow for Carriage Return.
}

void rtty_txbyte (char c) {
  rtty_txbit (0);            // Start bit
  for (byte i = 0; i < 8; i++) //8 bits in char (byte).
  {
    rtty_txbit(c & 1);
    c = c >> 1;
  }
  rtty_txbit (1);           // Stop bit 1
  rtty_txbit (1);           // Stop bit 2 - Teletype needs 2 stop bits

}

void rtty_txbit (byte bit) {
  digitalWrite(rtty1, bit);
  delayMicroseconds(9090);  //9.09 ms is the bit speed for 110 Baud
}

void rtty_txstring (char *string)              // *variable is a pointer to the variable
{

  /* Simple function to send a char at a time to
   ** rtty_txbyte function.
   ** Each char is one byte (8 Bits)
  */

  char c;

  c = *string++;
  while ( c != '\0')             // \0 denotes end of string
  {
    rtty_txbyte (c);
    c = *string++;               //move to c to next char of string
  }
}

I had a blast doing this and learned a bunch. Thanks to all of those who helped.

I will try to work up some bells and whistles now. Then, maybe, see if I can get the Arduino to listen to the keyboard.

Greg

Very cool!

  delay(500); // Pause to allow for Carriage Return.

It's traditional to add "padding" bytes containing null or "deletes"

void rtty_txstring (char *string)              // *variable is a pointer to the variable
    :
  c = *string++;
  while ( c != '\0')             // \0 denotes end of string
  {
    rtty_txbyte (c);
    if (x == '\r' || c == '\n') { //  Carriage movement may require padding
       rtty_txbyte(0);
       rtty_txbyte(0);
       rtty_txbyte(0);
  }
    c = *string++;               //move to c to next char of string
  }
}

I tried adding 3 NUL characters but I couldn't get them to work. Your suggestion is much more graceful than I was trying. I will give it a try.

Greg

I wish I had an ASR-33. Still looking for a mostly working one.

I found this a few months ago.
https://wiki.theretrowagon.com/wiki/20ma_current_loop_to_RS-232_conversion

It appears to answer the hardware portion of the interface. Both transmit and receive.
I would add a MAX232 for protection to the Arduino pins:

That is a find. Did you actually find the PCB and everything, or just the schematic.
Here are some pages from TV TYPEWRITER COOKBOOK which converts current loop directly to TTL.

If you don't have any reason to convert to RS232 (if you are just going to connect to Arduino) then you can skip the -12 power supply.

There are other pages about interfacing the ASR33 in the TV TYPEWRITER COOKBOOK and it is a good resource still available from Amazon.

Ebay has several different RS232 to TTL converters available for a few bucks and they are made up with connectors, etc.

I like having the RS232 intermediate interface because I can plug the Teletype directly into my PC. BTW finding a PC with a serial port can be a challenge also. And, beware, some of the USB to RS232 adapters out there will NOT go 110 N82.

There is an ASR33 on EBAY now for $500. You don't see them around any longer. That's one of the reasons I am spending all the time getting my running again.

Once you get the ASR running, keep it running. They need regular exercise.

Very few resources also, even on the Internet, for repair parts, or even advice. All those guys are mostly long gone.

I was lucky I have had mine for decades and I remember quite a bit about it. But even so, I have looked here for advice.

The code I posted below works, though I have made some improvements.

Good Luck!

Pages from TV Typewriter Cookbook.pdf (217 KB)