Skip to content

Commit bb089b9

Browse files
committed
Update README.
1 parent 8ca0c25 commit bb089b9

File tree

1 file changed

+99
-34
lines changed

1 file changed

+99
-34
lines changed

README.md

+99-34
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ _PacketSerial_ is an small, efficient, library that allows [Arduinos](http://www
1111

1212
## Background
1313

14-
_"Why do I need this?"_ you may ask. The truth is that you may not need it if you are converting your values to ASCII strings and separating them with a known character (like a carriage return `\r` and a line feed `\n`) before sending them. This is what happens if you call and `Serial.println()`. For instance, if you just want to send a byte with the value of 255 and follow it with a new line character (i.e. `Serial.println(255)`) the Arduino automatically converts the number to the equivalent printable ASCII characters, sending 5 bytes total. As a result the receiver won't just receive a byte for the number and two bytes for the carriage return and new line character. Instead it will receive a stream of 5 bytes:
14+
_Why do I need this?_ you may ask. The truth is that you may not need it if you are converting your values to ASCII strings and separating them with a known character (like a carriage return `\r` and a line feed `\n`) before sending them. This is what happens if you call and `Serial.println();`. For instance, if you just want to send a byte with the value of 255 and follow it with a new line character (i.e. `Serial.println(255);`) the Arduino automatically converts the number to the equivalent printable ASCII characters, sending 5 bytes total. As a result the receiver won't just receive a byte for the number and two bytes for the carriage return and new line character. Instead it will receive a stream of 5 bytes:
1515

1616
```
1717
50 // ASCII '2'
@@ -21,7 +21,7 @@ _"Why do I need this?"_ you may ask. The truth is that you may not need it if yo
2121
10 // ASCII '\n'
2222
```
2323

24-
The receiver must then collect the 3 ASCII characters `{ '2', '5', '5' }`, combine them and convert them back into a single byte with a value of `255`. This process can get complicated when the user wants to send large quantities of structured data between the Arduino and a receiver.
24+
The receiver must then collect the 3 ASCII characters { '2', '5', '5' }, combine them and convert them back into a single byte with a value of `255`. This process can get complicated when the user wants to send large quantities of structured data between the Arduino and a receiver.
2525

2626
One way to send a _packet_ of data without this library is to send each byte separated by a comma or space and terminate the sequence with a new line character. Thus, to send the value `255` and the value `10`, one might call:
2727

@@ -46,7 +46,14 @@ The receiver will actually see a stream of 7 bytes:
4646

4747
In this case, the receiver must then collect the ASCII characters, combine them, skip the delimiter (the comma in this case) and then process the packet when a new line is encountered. While effective, this method doesn't scale particularly well. Bytes with values larger than 9 are encoded as 2 bytes and bytes with values larger than 99 are encoded as 3 bytes, etc. If the user would like to send the number 4,294,967,295 (the maximum value of a 4 byte `unsigned long`), it would be encoded as 10 bytes. This means that there is an overhead of 6 extra bytes to transmit a 4 byte `unsigned long`.
4848

49-
An alternative to ASCII encoding is to write the bytes directly to using the `Serial.write()` methods. These methods do not convert the byte values to ASCII. So if the user wants to send a single byte with the value of 255 and follow it with a new line character (i.e. `Serial.write(255); Serial.write('\n');`), the receiver will see a stream of 2 bytes:
49+
An alternative to ASCII encoding is to write the bytes directly to using the `Serial.write()` methods. These methods do not convert the byte values to ASCII. So if the user wants to send a single byte with the value of `255` and follow it with a new line character:
50+
51+
```c++
52+
Serial.write(255);
53+
Serial.write('\n');
54+
```
55+
56+
the receiver will see a stream of 2 bytes:
5057

5158
```
5259
255 // The value transmitted.
@@ -59,82 +66,139 @@ Another coding available in PacketSerial is [Serial Line Internet Protocol](http
5966
## Use
6067
### PacketSerial
6168

62-
The `PacketSerial` class wraps the standard Arduino `Serial` class to automatically encode and decode byte packets. Thus users can still call methods on the `Serial` object (e.g. `Serial.write()`, the built in `serialEvent()` callback etc), but it is not recommended. Users are advised to let PacketSerial manage all Serial communication via the packet handler callback for incoming packets and the `send(const uint8_t* buffer, size_t size) const` method for outgoing packets. Mixing raw Serial calls with `PacketSerial` may lead to unexpected encoding and decoding results, as the endpoint will not know what data is encoded and what data is not.
69+
`PacketSerial` class wraps the Arduino `Stream` class to automatically encode and decode byte packets that are sent and received. Typically serial communication uses the default `Serial` object, which implements the `Stream` class. In most cases, `PacketSerial` should be given exclusive access to the serial `Stream` (e.g. for a default setup using `Serial`, users should avoid calling functions like `Serial.print()`, `Serial.write()`, etc directly). Data should be sent via the `send(const uint8_t* buffer, size_t size) const` method and received in a `PacketSerial` callback function (see below).
6370

6471
### Setup
72+
#### Basic
6573

66-
For Arduino boards with more than one serial port, `PacketSerial` the desired serial port can be specified with the `begin` method, i.e.
74+
To use the default `Serial` object and the default communication settings (usually `SERIAL_8N1`), set up `PacketSerial` like this:
6775

6876
```c++
69-
void begin(unsigned long speed, uint8_t config, size_t port = 0)
77+
PacketSerial myPacketSerial;
78+
79+
void setup()
80+
{
81+
myPacketSerial.begin(9600);
82+
myPacketSerial.setPacketHandler(&onPacketReceived);
83+
}
7084
```
7185

72-
Where:
86+
### Advanced
87+
88+
For a non-default Serial connection, a class implementing the `Stream` interface should be configured and then set for the `PacketSerial` instance.
89+
90+
#### Using A Non-Standard Serial Configuration
91+
92+
PacketSerial myPacketSerial;
93+
94+
```c++
95+
void setup()
96+
{
97+
Serial.begin(300, SERIAL_7N1);
98+
myPacketSerial.setStream(&Serial);
99+
myPacketSerial.setPacketHandler(&onPacketReceived);
100+
}
101+
```
73102

74-
| _Arduino_ Serial Port | _PacketSerial_ Port Number |
75-
| ------------- |:-------------:|
76-
| `Serial` | 0 |
77-
| `Serial1` | 1 |
78-
| `Serial2` | 2 |
79-
| `Serial3` | 3 |
103+
#### Using Secondary Serial Ports (e.g. Serial1, Serial2, etc)
80104

81-
Alternatively, to use a software serial port or other pre-configured network stream you can use an alternate `begin` method, this time with only a `Stream*` as argument, e.g.:
82105
```c++
83-
void begin(Stream* serial)
106+
PacketSerial myPacketSerial;
107+
108+
void setup()
109+
{
110+
Serial1.begin(9600);
111+
myPacketSerial.setStream(&Serial1);
112+
myPacketSerial.setPacketHandler(&onPacketReceived);
113+
}
84114
```
85115

86-
To set this up, you might do the following:
116+
#### Using SoftwareSerial
117+
87118
```c++
88119
PacketSerial myPacketSerial;
89120
SoftwareSerial mySoftwareSerial(10, 11);
90121

91-
// In this case the serial port has to be initialized before passing it to PacketSerial.
92-
mySoftwareSerial.begin(38400);
93-
myPacketSerial.begin(&mySoftwareSerial);
122+
void setup()
123+
{
124+
mySoftwareSerial.begin(38400);
125+
myPacketSerial.setStream(&mySoftwareSerial);
126+
myPacketSerial.setPacketHandler(&onPacketReceived);
127+
}
94128
```
95129
96-
On boards with multiple serial ports, this strategy can also be used to set up two Serial streams, one for packets and one for debug ASCII (see [this discussion](https://github.com/bakercp/PacketSerial/issues/10) for more).
130+
#### Other Streams
97131
98-
To receive decoded packets, the user should register a packet callback. The packet callback should be placed in your main Arduino Sketch and should have a method that looks like this:
132+
Any class that correctly implements the `Stream` interface should work, which includes some network communication objects.
133+
134+
### Loop
135+
136+
In order to processing incoming serial packets, the user must call the `update()` method at the end of the `loop()` method.
99137
100138
```c++
101-
void onPacket(const uint8_t* buffer, size_t size)
139+
void loop()
102140
{
103-
// Process your decoded incoming packet here.
141+
// Your program here.
142+
143+
144+
// Call update to receive, decode and process incoming packets.
145+
myPacketSerial.update();
104146
}
147+
105148
```
106149

107-
Your callback can have any name and should be registered in the `setup()` method like this:
150+
### Receiving Packets
151+
152+
All packets are received via handler functions. A typical handler function would be registered in the `void setup()` function like:
108153

109154
```c++
110-
void setPacketHandler(PacketHandlerFunction onPacketFunction)
155+
PacketSerial myPacketSerial;
156+
157+
void setup()
158+
{
159+
myPacketSerial.begin(9600);
160+
myPacketSerial.setPacketHandler(&onPacketReceived);
161+
}
111162
```
112163

113-
### Main Loop
164+
The `onPacketReceived` function can take two forms. The simplest looks like this:
114165

115-
In order to processing incoming serial packets, the user must call the `update()` method at the end of the `loop()` method.
116166

117167
```c++
118-
void loop()
168+
void onPacketReceived(const uint8_t* buffer, size_t size)
119169
{
120-
// Your program here.
170+
// Process your decoded incoming packet here.
171+
}
172+
```
173+
174+
For more advanced programs with multiple PacketSerial instances and a shared handler, it may be useful to know which PacketSerial instance received the packet. In this case you could define a callback like this:
121175
122-
serial.update();
176+
```c++
177+
void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size)
178+
{
179+
if (sender == &myPacketSerial)
180+
{
181+
// Do something with the packet from myPacketSerial.
182+
}
183+
else if (sender == &myOtherPacketSerial)
184+
{
185+
// Do something with the packet from myOtherPacketSerial.
186+
}
123187
}
124188
125189
```
126190

127191
### Sending Packets
128192

129-
To send packets call the `send()` method. The send method will take a packet (an array of bytes), encode it, transmit it and send the packet boundary marker (usually `0`). To send the values 255 and 10, one might do the following:
193+
To send packets call the `send()` method. The send method will take a packet (an array of bytes), encode it, transmit it and send the packet boundary marker. To send the values `255` and `10`, one might do the following:
130194

131195
```c++
132196

133197
// Make an array.
134-
uint8_t myPacket[] { 255, 10 };
198+
uint8_t myPacket[2] = { 255, 10 };
135199

136200
// Send the array.
137-
serial.send(myPacket, 2);
201+
myPacketSerial.send(myPacket, 2);
138202
```
139203
140204
## Examples
@@ -151,5 +215,6 @@ See the included examples for further usage options.
151215
## Changelog
152216
See [CHANGELOG.md](CHANGELOG.md)
153217
218+
154219
## License
155-
See [LICENSE.md](LICENSE.md)
220+
See [LICENSE.md](LICENSE.md)

0 commit comments

Comments
 (0)