0

Trinket and Serial I/O
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Trinket and Serial I/O

by thekitty on Mon Sep 09, 2013 1:07 pm

As noted in the Trinket tutorials, the USB port will not perform USB/Serial I/O.

But the SoftwareSerial library works well. If you only need to send (or receive) data, only one GPIO pin and a ground connection is needed. You'll need 2 pins for transmit+receive.

Image

Code: Select all | TOGGLE FULL SIZE
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 1); // Receive Pin, Transmit Pin although I only transmit here

void setup() 
{
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.println("Setup Done");
}

void loop() // run over and over
{
  mySerial.println("hello");
  delay(1000);
}


To test your serial connection, the easiest way is to feed the transmit pin to the receive pin of an FTDI friend or other TTL serial to USB device (I tried a Foca board from Iteadstudio, but Adafruit sells some nice FTDI based solutions).

Use the Terminal program of choice for your operating system. I used PuTTY on Windows 7. Look to see which USB COM port the converter cable is using (mine was COM10, yours will vary), then set PuTTY to COM10, 9600 baud, 8 bit, 1 stop bit, no parity. When the Trinket resets, you'll see the text "Setup Done", then "Hello" once a second. If you get nothing, check your COM port and wiring (Trinket transmit pin to serial converter receive pin), if you get garbage characters and no text, check your baud rate and settings.

With the basics done, you can then communicate with serial sensors, larger Arduinos, PCs or Raspberry Pis.

Mike

PS The NeoPixel is not required, I had it on the breadboard from the previous circuit. Very blinky :)

thekitty
 
Posts: 645
Joined: Sat Mar 24, 2012 8:56 pm
Location: Mid-Atlantic

Re: Trinket and Serial I/O

by mrburnette on Wed Sep 18, 2013 10:51 am

Trinket is a 'resource constrained' hardware environment; which is to say you only have one port (B) and only a few pins. So, in those cases where you are using SoftwareSerial() and you only wish to Send outbound (Tx), then it is beneficial to not have to specify a Rx pin. Arduino Forum Global Moderator Nick Gammon has subclassed the SoftwareSerial library to eliminate the need to use a Tx pin. This is good news for the Trinket. Reference: http://forum.arduino.cc/index.php?topic=112013.0

So, here is my code to send a test message @96oo Baud on an 8MHz Trinket at either 3.3V or 5V. You must first download Nick's files and put them in the C:\Users\owner\Documents\Arduino\libraries where "owner" is your Windows UserID. Note, different versions of Windows may require tweaking the above path.

Code: Select all | TOGGLE FULL SIZE

/* Adafruit Trinket  for 5V or 3.3V designs
 Software Serial Count test and LED blink
 Public domain example by: M. Ray Burne
 Binary sketch size: 2,814 bytes (of a 5,372 byte maximum)

 This example uses Nick Gammon's subclassing of SoftwareSerial to support only send pin
 Reference: http://forum.arduino.cc/index.php?topic=112013.0
 
                               +---\/---+
(Reset)              (D 5) PB5 |1      8| VCC
(USB-) AnalogA3      (D 3) PB3 |2      7| PB2 (D 2) AnalogA1,I2C&SPI Clk
(USB+) PWM, AnalogA2 (D 4) PB4 |3      6| PB1 (D 1) PWM1,SPI(LED)
                            GND |4      5| PB0 (D 0) PWM0, I2C, SPI
                                +--------+
 */

#include <SendOnlySoftwareSerial.h>
#include <Streaming.h>

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

int blinkCount ;
const int LEDpin = 1;
boolean PIND;

SendOnlySoftwareSerial mySerial(0); // Transmit Only on PB0

void setup() 
{
  pinMode(LEDpin, OUTPUT);
  digitalWrite(LEDpin, LOW); // low == off
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.println("Setup Done");
}

void loop() // run over and over
{
  PIND = !PIND; // flip boolean PIND
  digitalWrite(LEDpin, PIND);
  // Every minute, show the freeRam value
  if (!(blinkCount % 60)) mySerial << (F("Free RAM= ")) << freeRam() << "\r\n\r\n" ;
  mySerial << (F("count= ")) << blinkCount++ << "\r\n" ;
  delay(1000);
}



For those who have never used Streaming.h, I think you will be pleasantly surprised at how it simplifies your print output.
Example output:
Setup Done
Free RAM= 431

count= 0
count= 1
count= 2
count= 3
count= 4
count= 5
count= 6
...
count= 57
count= 58
count= 59
Free RAM= 431

count= 60
count= 61



Good luck and have fun!

Edited to add the FreeRam() function. This function can be left in your code while developing and just comment all use of the function with "//" after debugging and the linker will not link the code in your final compile.

Ray
mrburnette
 
Posts: 50
Joined: Tue Sep 10, 2013 9:15 pm

Re: Trinket and Serial I/O

by mrburnette on Fri Sep 20, 2013 12:45 pm

My previous post turned On the LED for 1 second and turned Off the LED for 1 second... or, 2 second time_period. This is not the way human eyes like to see 1 second timing :wink:

So, just to provide an alternate way of doing the blink, I edited the example. I also put a scope on my Trinket and found the RC clock was running a little fast, which means the delay() needs to be a little longer in total time to account for the period and improve the counting. In my measurement, I needed to add 18mS total and I noticed on the scope that the jitter was on both sides (996-1004) of the 1000 mS period once I programmed the Trinket and checked it on the scope - this is good, as the results over time average out closer to 1 second total... close enough for an egg-timer or darkroom timer but probably not acceptable as a 30-day clock!

Note that the serial routine that I am using is not the standard one (although it should work with the standard SoftwareSerial) Please see the above post for the source of the send-only routine.
I am using one of the Adafruit USB to serial cables:
http://www.adafruit.com/products/954 which are very nice.

What is happening in the code is that PIND alternates between True and False every loop.
The "if (!(blinkCount % 60))" statement only fires once per minute to print the Free Memory in the uC.
The "if (PIND)" statement (remember the loop() executes twice a second, once with a 50mS delay and once with a 968mS delay, so the PIND is flipping states and the if() will only fire true once and the "else" clause will execute only once. Perfect.

Code: Select all | TOGGLE FULL SIZE

#include <SendOnlySoftwareSerial.h>
#include <Streaming.h>

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

int blinkCount ;
const int LEDpin = 1;
boolean PIND;

SendOnlySoftwareSerial mySerial(0); // Transmit Only

void setup() 
{
  pinMode(LEDpin, OUTPUT);
  digitalWrite(LEDpin, LOW); // low == off
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.println("Setup Done");
}

void loop() // run over and over
{

  PIND = !PIND; // flip boolean PIND
  digitalWrite(LEDpin, PIND);
  if (PIND) {
    // Every minute, show the freeRam value
    if (!(blinkCount % 60)) mySerial << (F("Free RAM= ")) << freeRam() << "\r\n\r\n" ;
    mySerial << (F("count= ")) << blinkCount++ << "\r\n" ;
    delay(50);
  } else {
      delay(968); // RC a fast- slow down loop 18mS
  }
}
mrburnette
 
Posts: 50
Joined: Tue Sep 10, 2013 9:15 pm

Re: Trinket and Serial I/O

by thekitty on Wed Nov 20, 2013 1:56 pm

I heartily agree that the SendOnlySoftwareSerial library is excellent for working with Trinket & Gemma and using only one pin for transmit.

thekitty
 
Posts: 645
Joined: Sat Mar 24, 2012 8:56 pm
Location: Mid-Atlantic

Please be positive and constructive with your questions and comments.