├── tcr_dimensions.png
├── README.md
├── tiny_code_reader_back.svg
├── qwiic_connector.svg
└── tiny_code_reader_front.svg
/tcr_dimensions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moonshine-ai/tiny_code_reader_docs/HEAD/tcr_dimensions.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tiny Code Reader Developer Guide
2 | *Author [pete@usefulsensors.com](mailto:pete@usefulsensors.com), permanent link is [usfl.ink/tcr_dev](https://usfl.ink/tcr_dev)*
3 |
4 | ## Introduction
5 |
6 | The [Tiny Code Reader](https://usfl.ink/tcr) from [Useful Sensors](https://usefulsensors.com)
7 | is a small, low-cost hardware module that reads QR codes. It's designed to be
8 | a simple way to provision a system, for example by providing the wifi network
9 | name and password, or to provide input when there's no keyboard.
10 |
11 | This guide will explain what information the module can return, how to interpret
12 | that information, and how to integrate with a microcontroller like an Arduino or
13 | Raspberry Pi. You will need a basic understanding of electronics, enough to
14 | integrate a temperature sensor for example, but very little coding is required.
15 |
16 | * [Getting it Working](#getting-it-working)
17 | + [Connecting](#connecting)
18 | + [Mounting](#mounting)
19 | + [Powering Up](#powering-up)
20 | + [Reading Data](#reading-data)
21 | * [Configuration](#configuration)
22 | * [Sensor Characteristics](#sensor-characteristics)
23 | * [Example Code](#example-code)
24 | + [Useful Sensors Examples](#useful-sensors-examples)
25 | - [CircuitPython](#circuitpython)
26 | - [MicroPython](#micropython)
27 | - [Arduino](#arduino)
28 | - [Raspberry Pi Pico](#raspberry-pi-pico)
29 | - [Raspberry Pi](#raspberry-pi)
30 | - [Micro:bit](#microbit)
31 | - [Badger 2040](#badger-2040)
32 | + [Community Examples](#community-examples)
33 | * [Privacy](#privacy)
34 | * [Acknowledgements](#acknowledgements)
35 | * [Appendix](#appendix)
36 | + [Data Format](#data-format)
37 | + [C Struct Format](#c-struct-format)
38 | + [Python Data Format Strings](#python-data-format-strings)
39 | + [CAD File](#cad-file)
40 | + [Datasheet](#datasheet)
41 | + [Pre-production Modules](#pre-production-modules)
42 |
43 | ## Getting it Working
44 |
45 | Internally the Tiny Code Reader bundles an image sensor and a small
46 | microcontroller into a single board, but to make it as easy as possible to
47 | build into products we’ve tried to hide those implementation details. It
48 | returns information about any QR codes it sees over an I2C connection.
49 |
50 | ### Connecting
51 | The board uses a standard Qwiic connector for the I2C interface. This is
52 | designed so you can only plug it in one way, but the individual lines are shown
53 | in the diagram below for reference. You can find more information about this
54 | form factor at [SparkFun’s Qwiic page](https://www.sparkfun.com/qwiic), but it’s
55 | now widely supported by a lot of vendors, including with [Adafruit’s Stemma QT connector](https://learn.adafruit.com/introducing-adafruit-stemma-qt/what-is-stemma-qt).
56 | SparkFun also have a [guide for connecting to a Raspberry Pi](https://learn.sparkfun.com/tutorials/qwiic-hat-for-raspberry-pi-hookup-guide),
57 | and [another for Arduino Nanos](https://learn.sparkfun.com/tutorials/sparkfun-qwiic-shield-for-arduino-nano-hookup-guide). If you're using a standard
58 | connector, the wire colors are yellow for SCL, blue for SDA, red for 3.3V, and
59 | black for GND.
60 |
61 | The sensor supports I2C bus speeds of up to 400k baud. We expect
62 | 3.3V power, other voltage levels are not supported.
63 |
64 | 
65 |
66 | ### Mounting
67 |
68 | The sensor uses an image sensor internally, so you need to make sure that the
69 | lens has a clear field of view. It can be mounted in any orientation, that
70 | shouldn't affect the code recognition quality. There's a mounting hole for a
71 | screw in the top left, and some alternative pads in case you don't want to use
72 | a QWIIC connector but want to wire in directly. The edge with these pads is
73 | designed to snap off, in case you need to reduce the size of the board further.
74 |
75 | 
76 |
77 | 
78 |
79 | ### Powering Up
80 |
81 | Before you start trying to read information from the sensor, a good first step
82 | is to power it up and make sure it seems to be working correctly. To do this
83 | connect the GND and 3.3V lines from your microcontroller to the sensor. If
84 | you’re using a Qwiic socket on the MCU you’ll also be connecting the SDA and SDC
85 | automatically, but if you’re breaking out to individual pins don’t worry about
86 | them yet. With the sensor powered, bring up [a simple QR code](https://en.wikipedia.org/wiki/QR_code#/media/File:QR_code_for_mobile_English_Wikipedia.svg)
87 | on your phone and place it about fifteen centimeters or six inches in front of
88 | the module, facing the camera. You should see the LED on the front of the board
89 | rapidly flashing blue, and then turn green when the QR code is detected. It may
90 | take a bit of wiggling and moving back and forth to get a detection.
91 |
92 | ### Reading Data
93 |
94 | Once you have the sensor connected and mounted, you’ll want to start reading
95 | information from it. The code you use to do this will depend on the platform
96 | you’re using for the main controller device, but [here’s some C example code for
97 | a Raspberry Pi Pico](https://github.com/usefulsensors/tiny_code_reader_pico_c).
98 | The 7-bit peripheral address for the sensor is 0x0C, or 12 in decimal. Please
99 | note that some systems include the read/write bit in the address, making the
100 | 8-bit peripheral address 0x18 or 0x19.
101 |
102 | ```C
103 | if (!tiny_code_reader_read(&results)) {
104 | printf("No code results found on the i2c bus\n");
105 | sleep_ms(SAMPLE_DELAY_MS);
106 | continue;
107 | }
108 |
109 | if (results.content_length == 0) {
110 | printf("No code found\n");
111 | } else {
112 | printf("Found '%s'\n", results.content_bytes);
113 | }
114 | ```
115 |
116 | This shows how you read data from the peripheral. That data is a 16-bit
117 | unsigned integer containing the length of the read QR code content, followed by
118 | the content itself in a 254 byte array. If no QR code has been seen in the last
119 | scan period, the length will be zero, and so will the content array. If the
120 | length is greater than zero, any bytes after the end of the content will be set
121 | to zero, guaranteeing a zero-terminated string.
122 |
123 | The content will typically be a UTF-8-encoded Unicode string, but it's not
124 | guaranteed to be. As with all user inputs, you should sanitize and escape it
125 | before using it for anything sensitive. You can think of the reader like an
126 | input box on a website - users can enter whatever they want so it's important
127 | to check if you're using it to control system behavior.
128 |
129 | ## Configuration
130 |
131 | The only behavior that's configurable is the module's LED. By default it
132 | flashes blue while scanning, green when a valid QR code has been detected, and
133 | red when there was an error decoding the QR code. By writing 0x00 to register
134 | address 0x01 you can turn the LED off entirely.
135 |
136 | | Address | Name | Default | Description |
137 | | ------- | ---- | ------- | ----------- |
138 | | 0x01 | LED | 0x01 (On) | Set to zero to turn off LED |
139 |
140 | ## Reader Characteristics
141 |
142 | The module relies on an image sensor and computer vision to read QR codes, so
143 | it does require some illumination to work. The image sensor doesn’t include an
144 | IR filter, so using near-IR illumination from an LED should be possible in
145 | situations where visible light is not available, but we haven’t characterized
146 | the accuracy of the sensor in those conditions.
147 |
148 | The reader works best with comparatively simple QR codes (20 characters or
149 | less) but the only hard limit on the size is the 254 byte content array. The
150 | module is designed to be small and low cost, and so will not have the same
151 | accuracy and range of larger, more expensive commercial readers.
152 |
153 | The sensor has approximately a 110 degree field of view.
154 |
155 | The model runs about five times a second. The latency is approximately the time
156 | to perform one model iteration, so roughly 200 milliseconds. There's no
157 | pin raised raised when a QR code is found, so you will need to keep polling to
158 | catch recognitions.
159 |
160 | This version of the board requires 3.3V input, and consumes about 100 milliwatts
161 | of power (with about 5mW going to the LED when active).
162 |
163 | ## Example Code
164 |
165 | ### Useful Sensors Examples
166 |
167 | We have written samples for some of the most popular development platforms.
168 |
169 | #### CircuitPython
170 |
171 | [github.com/usefulsensors/tiny_code_reader_circuit_python](https://github.com/usefulsensors/tiny_code_reader_circuit_python)
172 |
173 | [github.com/usefulsensors/tiny_code_reader_trinkey_keyboard](https://github.com/usefulsensors/tiny_code_reader_trinkey_keyboard)
174 |
175 | #### MicroPython
176 |
177 | [github.com/usefulsensors/tiny_code_reader_wifi_micropython](https://github.com/usefulsensors/tiny_code_reader_wifi_micropython)
178 |
179 | #### Arduino
180 |
181 | [github.com/usefulsensors/tiny_code_reader_arduino](https://github.com/usefulsensors/tiny_code_reader_arduino)
182 |
183 | #### Raspberry Pi Pico
184 |
185 | [github.com/usefulsensors/tiny_code_reader_pico_c](https://github.com/usefulsensors/tiny_code_reader_pico_c)
186 |
187 | #### Raspberry Pi
188 |
189 | #### Micro:bit
190 |
191 | [github.com/usefulsensors/tiny_code_reader_micro_bit](https://github.com/usefulsensors/tiny_code_reader_micro_bit)
192 |
193 | #### Badger 2040
194 |
195 | [github.com/usefulsensors/tiny_code_reader_badger](https://github.com/usefulsensors/tiny_code_reader_badger)
196 |
197 |
198 | ### Community Examples
199 |
200 | We also love to feature projects created by makers, so if you'd like to see your
201 | guide, tutorial, or GitHub repo featured here, please send us a pull request
202 | adding it to this section of the documentation. We also collect maker guides at
203 | [our Hackster project hub](https://www.hackster.io/useful-sensors/projects).
204 |
205 | ## Privacy
206 |
207 | This module includes an image sensor, and we want to make sure that this doesn’t
208 | pose a threat to any of our users’ privacy. We’ve designed the module so that it
209 | is as resistant as possible to anyone accessing the raw image data, and only the
210 | metadata derived from each frame is available. We’ve also built it to have as
211 | slim an interface as possible, to reduce the possibility of malicious
212 | interference and make it simpler for third parties to audit our privacy claims.
213 |
214 | This approach does constrain what developers can do with the device. One obvious
215 | restriction is that we don’t allow you to access the image data, but we also
216 | don’t support flashing the firmware or model updating, because doing so could
217 | allow unchecked changes to the sensor’s behavior. Even though there’s a
218 | microcontroller on the board, we’re hoping that you’ll be able to get enough
219 | value out of its pre-programmed behavior to compensate for the inconvenience of
220 | this user protection approach.
221 |
222 | If you’re interested in learning more about this approach to system design, we
223 | have a [research paper describing what we call Machine Learning Sensors](https://arxiv.org/pdf/2206.03266.pdf).
224 |
225 | ## Acknowledgements
226 |
227 | This module uses an RP2040 MCU from Raspberry Pi to run the QR code recognition. It's been a great piece of hardware to work with, with more RAM and
228 | compute than anything else in its class.
229 |
230 | We have found the [zxing-cpp](https://github.com/zxing-cpp/zxing-cpp) a very
231 | well-written and maintained source of information on barcode decoding in general
232 | and QR codes in particular. Useful Sensors is proud to be a sponsor of the
233 | project and we encourage anyone who finds these sensors useful to [do so too](https://github.com/sponsors/axxel).
234 |
235 | Lee Jackson at [Arducam](https://arducam.com) has been a fantastic help
236 | sourcing high-quality, low-cost camera modules. If you need imaging solutions
237 | for your microcontroller projects I highly recommend [talking to him](mailto:admin@arducam.com).
238 |
239 | ## Appendix
240 |
241 | ### Data Format
242 |
243 | The inference result is stored as an array of bytes in the following format.
244 | Information about each member is described in detail above.
245 |
246 | | Byte Offset | Meaning |
247 | | ----------- | ------- |
248 | | 0 | Content Length (first byte) |
249 | | 1 | Content Length (second byte) |
250 | | 2 | Content Byte #0 |
251 | | 3 | Content Byte #1 |
252 | | ... | ... |
253 | | 256 | Content Byte #254 |
254 |
255 | ### C Struct Format
256 |
257 | The most up to date versions of these data structures can be found at [github.com/usefulsensors/tiny_code_reader_pico_c/blob/main/person_sensor.h](github.com/usefulsensors/tiny_code_reader_pico_c/blob/main/tiny_code_reader.h),
258 | but for reference here is a C struct version of the data format. The
259 | non-standard but commonly supported `packed` attribute is used to ensure no
260 | extra padding is introduced.
261 |
262 | ```C
263 | typedef struct __attribute__ ((__packed__)) {
264 | uint16_t content_length;
265 | uint8_t content_bytes[254]
266 | } tiny_code_reader_results_t;
267 | ```
268 |
269 | ### Python Data Format Strings
270 |
271 | A complete CircuitPython example of decoding the sensor data can be found at [github.com/usefulsensors/tiny_code_reader_circuit_python/blob/main/code.py](github.com/usefulsensors/tiny_code_reader_circuit_python/blob/main/code.py),
272 | but the format strings for struct decoding can be summarized as:
273 |
274 | ```Python
275 | TINY_CODE_READER_LENGTH_FORMAT = "H"
276 | TINY_CODE_READER_MESSAGE_SIZE = 254
277 | TINY_CODE_READER_MESSAGE_FORMAT = "B" * TINY_CODE_READER_MESSAGE_SIZE
278 | TINY_CODE_READER_I2C_FORMAT = TINY_CODE_READER_LENGTH_FORMAT + TINY_CODE_READER_MESSAGE_FORMAT
279 | ```
280 |
281 | ### CAD File
282 |
283 | [Here is a STEP file containing a model of the sensor](TCR_STEP.step).
284 |
285 | ### Datasheet
286 |
287 | [Here is a datasheet containing technical specifications for the module](https://usfl.ink/tcr_ds).
288 |
289 | ### Pre-production Modules
290 |
291 | Ahead of the full release we have given away a limited number of prototype
292 | modules with slightly older firmware versions. If you have bought a module,
293 | then it will be the final release version, but if you have received one of the
294 | pre-production versions through a contest of giveaway, it should function in a
295 | very similar way. Here are the differences:
296 |
297 | - The LED will be brighter, flashes green instead of blue, and there's no option to disable it.
298 | - The 256 byte result structure doesn't contain zeroes after the main message content. The contents are undefined, so you'll need to be careful to take the valid substring rather than decoding and relying on a zero terminator. All of the example code should handle this.
--------------------------------------------------------------------------------
/tiny_code_reader_back.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qwiic_connector.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tiny_code_reader_front.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------