Arduino et Co - Measure, Control, and Hack: Clever Tricks with ATmega328 Pro Mini Boards 3895765155, 9783895765155

With a simple Pro Mini board and a few other components, projects that 20 or 30 years ago were unthinkable (or would hav

135 114 11MB

English Pages 331 [332] Year 2022

Report DMCA / Copyright

DOWNLOAD PDF FILE

Table of contents :
Search…
Arduino & Co
All rights reserved.
Foreword
Acknowledgments
Table of Contents
1 • ATmega boards
1.1 The Pro Mini form factor
1.2 Uno versions
1.3 LilyPads and similar
1.4 The Nano board
2 • USB adapter with serial interface
2.1 USB adapters based on the CP2102
2.1.1 Project: Universal serial adapter cable
2.1.2 Serial Micro USB adapter
3 • Buying tips
3.1 Local suppliers and domestic mail order companies
3.1.1 Conrad Electronic
3.1.2 Reichelt Elektronik
3.1.3 Other online suppliers
3.2 Big International online stores
3.2.2 Ebay
3.2.3 Amazon
3.2.4 AliExpress
3.3 PayPal payment service
3.4 Customs
3.5 Caution: Pitfalls!
3.6 Buying basic equipment
3.6.1 The necessary tools
3.6.2 ATmega boards
3.6.3 Power supply
3.6.4 Standard components
3.6.5 Measuring tools
4 • Optimal construction
4.1 Construction on breadboard
4.2 Point-to-point construction
4.3 The thumbtack technique
4.4 Perfboards
4.5 Construction on printed circuit board
4.6 Pin header connectors
5 Programming
5.1 The Arduino-platform
5.2 Our first program
5.3 Uploading programs
5.4 Downloading the programs
6 • Board inputs and outputs
6.1 Reading inputs digitally
6.2 Reading analog inputs
6.2.1 Measuring voltages directly
6.2.2 Measuring using internal ref. & voltage divider
6.2.3 Measuring directly using the internal reference
6.2.4 Measuring current
6.2.5 Resistor measurement
6.3 Switching outputs digitally
7 • How do you switch something?
7.1 LEDs
7.1.1 Calculating the series resistance
7.1.2 LEDs in battery operation
7.1.3 Switching direction to ground or positive
7.1.4 Project: LED effect board
7.1.5 Battery protection for effect flasher
7.1.6 LEDs with integrated series resistor
7.1.7 Power LEDs
7.2 Switching using a transistor
7.2.1 BC547 transistor
7.2.2 BC337-40 transistor
7.2.3 BD435 transistor
7.2.4 Switching using MOSFETs
7.2.5 ULN2003A transistor array
7.2.6 ULN2803A transistor array
7.3 Switching using a relay
7.3.1 Solid-State relay
8 • Controlling, regulating, and dimming
8.1 Pulse-width modulation (PWM)
8.1.1 Project: Dimming LEDs in all colors
8.1.2 Quick color theory
8.1.3 Flowing color changes
8.2 Low-pass demodulation
8.3 Regulation with a feedback loop
8.4 Project: Adjustable constant current source
8.5 Project: Lithium-ion battery testing and charging station
8.6 Project: Adjustable current source with limits
9 • Controlling motors
9.1 DC motors
9.1.1 Transistor control
9.1.2 Speed control using PWM
9.1.3 Forward and reverse with an H-bridge
9.1.4 Full control using H-bridge and PWM
9.2 Stepper motors
9.2.1 How it works
9.2.2 The 28BYJ-48
9.2.3 Control using the A4988
9.2.4 Control using the DRV8825
9.2.5 Version A4988 vs. DRV8825
9.3 Brushless motors
9.3.1 Control using ESC
9.4 Servos
10 • Sensors
10.1 Analog sensors
10.1.1 Brightness sensor using LDR
10.1.2 NTC temperature measurement
10.1.3 Analog joystick
10.1.4 Measuring light with a photodiode
10.2 Digital measurements
10.2.1 TL1838 or VS1838B infrared receiver
10.2.2 HC-SR04 ultrasonic distance sensor
10.2.3 HC-SR501 motion sensor
10.2.4 The I²C interface
10.2.5 BMP180 air pressure sensor
10.2.6 MPU-6050 accelerometer
10.2.7 HMC5883L magnetic field sensor
10.2.8 GY-87 multi-sensor
11 • Other components
11.1 RF remote control
11.2 Seven-segment displays
11.2.1 Basic program for 1 to 6 digits
11.2.2 Project: Voltmeter
11.2.3 Project: Thermometer
11.3 Text displays with back-lighting
11.4 Mini lasers
11.5 SD card module
12 • Rechargeable batteries and accessories
12.1 Functionality and handling
12.2 Protection circuit
12.3 Connecting rechargeables in series
12.4 Balancers
12.5 USB charging regulators
13 • Clever hacks and tricks
13.1 Measuring battery level without components
13.2 Arduino in deep sleep
13.3 Low-battery switch-off
13.4 Pro Mini battery operation
13.5 Project: Electronic die
13.6 Analog measurement without waiting
13.7 Project: Universal remote control receiver
13.8 Project: Extreme altimeter
13.9 Project: Infrasound recorder
Index
Recommend Papers

Arduino et Co - Measure, Control, and Hack: Clever Tricks with ATmega328 Pro Mini Boards
 3895765155, 9783895765155

  • 0 0 0
  • Like this paper and download? You can publish your own PDF file online for free in a few minutes! Sign Up
File loading please wait...
Citation preview

books books

books

Measure, Control, and Hack Clever Tricks with ATmega328 Pro Mini Boards With a simple Pro Mini board and a few other components, projects that 20 or 30 years ago were unthinkable (or would have cost a small fortune) are realized easily and affordably in this book: From simple LED effects to a full battery charging and testing station that will put a rechargeable through its paces, there’s something for everyone. All the projects are based on the ATmega328 microcontroller, which offers endless measuring, switching, and control options with its 20 input and output lines. For example, with a 7-segment display and a few resistors, you can build a voltmeter or an NTC-based thermometer. The Arduino platform offers the perfect development environment for programming this range of boards. Besides these very practical projects, the book also provides the necessary knowledge for you to create projects based on your own ideas. How to measure, and what? Which transistor is suitable for switching a certain load? When is it better to use an IC? How do you switch mains voltage? Even LilyPad-based battery-operated projects are discussed in detail, as well as many different motors, from simple DC motors to stepper motors.

Robert Sontheimer was immediately on board when the first home computers arrived in our living rooms some 40 years ago, with his ZX81 and C64. Back then, he converted a plotter into a scanner, among other quirky and original ideas, and today he uses Arduino Pro Minis to control entire CNC laser machines and has even invented a matching suction system: his “self-changing toilet paper filter.” In his office, he has a magnet that’s been levitating for years – controlled by a Pro Mini, of course. Just a regular freak.

Sensors are another exciting topic: For example, a simple infrared receiver that can give disused remote controls a new lease on life controlling your home, and a tiny component that can actually measure the difference in air pressure between floor and table height!

Elektor International Media BV www.elektor.com

Arduino & Co – Measure, Control, and Hack • Robert Sontheimer

Arduino & Co

Arduino & Co

Measure, Control, and Hack #define

Clever Tricks with me ATmega328 Pro Mini Boards asure_pin A3 // Meas uring

input (A0 and A1 us ed

float r_ntc25 = 50 000; // resistance float r_fixed = 47 of the NTC at 25 d 000; // fixed resi stor (example 47 float r_factor[33] ki = // R-factor at -30 to +130 degree 5°) NTC version 39 50 {17.3, 12.8, 9.59, 7.25, 5.51, 4.23, 3.27, 2.54, 1.99, 0.81, 0.656, 0.535, 1. 0.438, 0.36, 0.3, 0.25, 0.21, 0.176, 0.107, 0.091, 0.07 0 79, 0.0671, 0.0585 , 0.0507, 0.0441, 0.0294}; 0.03

byte digits = 4; // number of digi ts boolean common_ano de = false; // fa lse for common ca byte segment_pin[ thod 8] = {11,A1,6,8,9 ,12,5,7}; // a,b, byte digit_pin[6] c,d,e = {4,A0,13,10}; // last to first digi t int frequency = 20 0; // frequency of display in Hz (abo float change_frequ ut ency = 0.5; // re fresh display ever byte segments[20] y 2 = // bit pattern (a to g) for the di ffer B1111110, B0110000 , B1101101, B11110 01, B0110011, // B1011011, B1011111 0 , B1110000, B11111 11, B1111011, // B1110111, B0011111 5, ,Robert B100Sontheimer 1110, B0111101, B1 001111, // A,

Arduino & Co – Measure, Control, and Hack

o This is an Elektor Publication. Elektor is the media brand of Elektor International Media B.V. PO Box 11, NL-6114-ZG Susteren, The Netherlands Phone: +31 46 4389444

o All rights reserved. No part of this book may be reproduced in any material form, including photocopying, or storing in any medium by electronic means and whether or not transiently or incidentally to some other use of this publication, without the written permission of the copyright holder except in accordance with the provisions of the Copyright Designs and Patents Act 1988 or under the terms of a licence issued by the Copyright Licencing Agency Ltd., 90 Tottenham Court Road, London, England W1P 9HE. Applications for the copyright holder's permission to reproduce any part of the publication should be addressed to the publishers.

o Declaration The Author and Publisher have used their best efforts in ensuring the correctness of the information contained in this book. They do not assume, and hereby disclaim, any liability to any party for any loss or damage caused by errors or omissions in this book, whether such errors or omissions result from negligence, accident, or any other cause.

o British Library Cataloguing in Publication Data A catalogue record for this book is available from the British Library ISBN 978-3-89576-515-5

Print

ISBN 978-3-89576-51 -

eBook

o © Copyright 2022: Elektor International Media B.V. (2022-08 / 1st) Prepress Production: Robert Sontheimer English translation: Brian Tristam Williams (and the author) Printed in the Netherlands by Ipskamp Printing, Enschede

Elektor is part of EIM, the world's leading source of essential technical information and electronics products for pro engineers, electronics designers, and the companies seeking to engage them. Each day, our international team develops and delivers high-quality content - via a variety of media channels (including magazines, video, digital media, and social media) in several languages - relating to electronics design and DIY electronics. www.elektormagazine.com

Arduino & Co Measure, Control, and Hack e er ri

ith

ro M n

me

● o ert

ont ei

er

o r

Arduino & Co – Measure, Control, and Hack

4

Foreword

Foreword I remember it like it was yesterday. I paged through the electronics catalog that had just arrived, and saw a new “home computer,” which fascinated me immediately. Not yet available, but announced, it would retail for the equivalent of over 600 euro – the Commodore 64. I knew immediately: One day, I would buy one! As you can guess, I’m not the youngest anymore. It must have been around 1982, and I was still in school. Two years later, that time came, and I could finally afford the C64. Back then, we programmed in the BASIC programming language, or directly in assembler. I controlled everything I could with the C64, because it had a “User Port” offering 8 data lines, all of which could be used as digital inputs and outputs. Today, for not much more than a couple of euro, you can get small microcontroller boards, which are much faster, and in some areas can do much more than the home computers of back then. The small Pro Mini board with an ATmega328P microcontroller has no keyboard or video output, of course. But, otherwise, it’s a fully-fledged, freelyprogrammable small computer with numerous input and output pins, which you can use to measure, control, and switch things as you please. That’s exactly what this book is about: Simple, inexpensive solutions for every purpose.

Robert Sontheimer

Acknowledgments I’d like to thank Timo Missel for numerous small jobs on this book, Matthias Abele for his tips and corrections, and, last but not least, Mr. Denis Meyer from Elektor Publishing, who was at my side in word and deed throughout the book project. For this English-language edition, my special thanks also go to the translator, Mr. Brian Tristam Williams, for his good work and cooperation.

5

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 2

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Table of Contents Foreword.................................................................................................................................. 5 Chapter 1 • ATmega boards............................................................................................ 14 1.1 The Pro Mini form factor..................................................................................14 A computer for a few euro............................................................................................ 15 5 V / 16 MHz and 3.3 V / 8 MHz versions............................................................... 16 ATmega328P and ATmega168PA................................................................................ 16 Pin layouts.......................................................................................................................... 17 1.2 Uno versions.......................................................................................................................... 18 1.3 LilyPads and similar............................................................................................................ 19 16 MHz LilyPads.................................................................................................................. 20 1.4 The Nano board.................................................................................................................... 20 Chapter 2 • USB adapter with serial interface ..........................................................21 2.1 USB adapters based on the CP2102 ............................................................................. 21 2.1.1 Project: Universal serial adapter cable ........................................................ 22 Construction............................................................................................................. 22  Tip: Neat soldering............................................................................................ 24 Usage......................................................................................................................... 26 2.1.2 Serial Micro USB adapter................................................................................... 26 Chapter 3 • Buying tips.....................................................................................................27 3.1 Local suppliers and domestic mail order companies .............................................. 27 3.1.1 Conrad Electronic................................................................................................. 27 3.1.2 Reichelt Elektronik............................................................................................... 28 3.1.3 Other online suppliers ........................................................................................ 28 3.2 Big International online stores .....................................................................28 3.2.2 Ebay........................................................................................................................... 28 Search settings....................................................................................................... 29 Security on Ebay..................................................................................................... 29 3.2.3 Amazon.................................................................................................................... 29 3.2.4 AliExpress................................................................................................................ 30 AliExpress shipping costs..................................................................................... 30 Buyer Protection on AliExpress........................................................................... 30 3.3 PayPal payment service ..................................................................................................... 31 3.4 Customs................................................................................................................................... 32 3.5 Caution: Pitfalls!................................................................................................................... 32 Fake items............................................................................................................................ 32 False information................................................................................................................ 33 False promises.................................................................................................................... 33 3.6 Buying basic equipment.................................................................................. 34 3.6.1 The necessary tools............................................................................ 34 Project: The simplest soldering station in the world ...............................34 6

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 3

2022-07-27 20:20

Table of Contents

Additional tools...................................................................................................... 36 3.6.2 ATmega boards.....................................................................................36 Serial adapters...................................................................................................... 36 3.6.3 Power supply.........................................................................................37 Mains power supplies.......................................................................................... 37 The thing about current and voltage................................................................. 37 Disposable or rechargeable battery ............................................................... 39 Lithium-ion rechargeables................................................................................. 39 Warning: Fake batteries..................................................................................... 40 Charge controller with protection circuit ..................................................... 41 3.6.4 Standard components........................................................................ 41 Resistors.................................................................................................................. 41 The E12 series......................................................................................................... 41 Capacitors................................................................................................................ 42 LEDs........................................................................................................................... 43 Transistors............................................................................................................... 43 Buzzer....................................................................................................................... 44 Jumper wires.......................................................................................................... 44 3.6.5 Measuring tools....................................................................................45 Multimeter............................................................................................................... 45 Infrared thermometer......................................................................................... 45 Vernier calipers...................................................................................................... 46 Chapter 4 • Optimal construction ..................................................................................47 4.1 Construction on breadboard............................................................................................ 47 4.2 Point-to-point construction ............................................................................................... 48 4.3 The thumbtack technique................................................................................................. 49 4.4 Perfboards............................................................................................................................... 49 Hole matrix.......................................................................................................................... 49 Stripboard............................................................................................................................ 50 Other grid arrangements.................................................................................................. 50 4.5 Construction on printed circuit board ........................................................................... 51 4.6 Pin header connectors........................................................................................................ 52 Coded connections............................................................................................................. 52 Chapter 5 Programming....................................................................................................53 5.1 The Arduino-platform......................................................................................................... 53 5.2 Our first program................................................................................................................. 54 Syntax: setup() and loop() functions ....................................................................... 54 Sketch: Our first program............................................................................................. 55 5.3 Uploading programs............................................................................................................ 56 5.4 Downloading the programs.............................................................................................. 57 Chapter 6 • Board inputs and outputs......................................................................... 58

7

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 4

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

6.1 Reading inputs digitally ...................................................................................58 Syntax: Variables............................................................................................................. 60 Syntax: pinMode(), digitalRead() and digitalWrite() ..........................................61 Syntax: Comparisons and conditions....................................................................... 62 Syntax: while and do-while loops.............................................................................. 63 Pushbutton switch............................................................................................................ 63 Sketch: Pushbutton switch........................................................................................... 64 6.2 Reading analog inputs..................................................................................... 65 Reference voltage............................................................................................................ 65 VCC as reference.............................................................................................................. 65 Internal reference............................................................................................................ 66 External reference.............................................................................................................. 66 Syntax: analogRead() and analogReference() ...................................................... 66 6.2.1 Measuring voltages directly .............................................................67 Syntax: Defining constants............................................................................... 67 Syntax: Serial transmission.............................................................................. 68 Syntax: Calculations and assignments......................................................... 68 Calculation pitfalls.................................................................................................. 69 Syntax: Rounding up and down...................................................................... 69 Sketch: Measuring voltages up to VCC ........................................................ 70 Calibration................................................................................................................ 71 6.2.2 Measuring using internal ref. & voltage divider ........................71 Possible ranges...................................................................................................... 72 Sketch: Measuring using internal ref. & voltage divider ........................72 Calibration................................................................................................................ 74 6.2.3 Measuring directly using the internal reference .......................74 Tip: Commenting out lines................................................................................ 75 Calibration................................................................................................................ 75 6.2.4 Measuring current...............................................................................76 Sketch: Measuring current................................................................................ 76 Possible ranges...................................................................................................... 78 Calibration................................................................................................................ 79 6.2.5 Resistor measurement.......................................................................80 Sketch: Resistance measurement.................................................................. 81 Swapping resistors................................................................................................. 82 Calibration................................................................................................................ 82 6.3 Switching outputs digitally .............................................................................82 Chapter 7 • How do you switch something? ..............................................................83 7.1 LEDs....................................................................................................................... 83 7.1.1 Calculating the series resistance .................................................................... 84 7.1.2 LEDs in battery operation.................................................................................. 84 7.1.3 Switching direction to ground or positive ................................................... 85 7.1.4 Project: LED effect board..................................................................86 8

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 5

2022-07-27 20:20

Table of Contents

Determining resistor vales................................................................................... 87

LilyPad construction template .......................................................................... 88 Pro Mini construction template ........................................................................ 89 Syntax: Arrays....................................................................................................... 90 Syntax: for loop.................................................................................................... 90 Syntax: delay() and system time................................................................... 91 Simple LED effect................................................................................................. 92 Sketch: LED rotation effect.............................................................................. 92 Syntax: Random values with random()....................................................... 94 LED running light effects ................................................................................... 94 Sketch: LED running light effects................................................................... 95 Other Blink applications........................................................................................ 97 7.1.5 Battery protection for effect flasher.............................................................. 97 7.1.6 LEDs with integrated series resistor .............................................................. 98 7.1.7 Power LEDs............................................................................................................. 98 7.2 Switching using a transistor.......................................................................... 99 7.2.1 BC547 transistor................................................................................................ 100 7.2.2 BC337-40 transistor.......................................................................................... 101 7.2.3 BD435 transistor................................................................................................ 101 Tip: Heat test...................................................................................................... 102 7.2.4 Switching using MOSFETs............................................................................... 102 The NTD4906N and IRLR8726PbF ............................................................... 103 Tip: Thermally conductive adhesive ........................................................... 104 7.2.5 ULN2003A transistor array............................................................................. 104 7.2.6 ULN2803A transistor array................................................................................. 105 7.3 Switching using a relay.................................................................................106 7.3.1 Solid-State relay................................................................................................ 107 Chapter 8 • Controlling, regulating, and dimming ................................................ 108 8.1 Pulse-width modulation (PWM).................................................................108 Syntax: analogWrite()................................................................................................. 109 8.1.1 Project: Dimming LEDs in all colors............................................109 8.1.2 Quick color theory................................................................................................ 110 8.1.3 Flowing color changes...................................................................................... 111 Syntax: sin() and cos()................................................................................... 111 Sketch: Flowing color changes..................................................................... 112 Tip: Small test with LED effect board ........................................................ 113 8.2 Low-pass demodulation................................................................................ 114 Time constant τ.............................................................................................................. 114 Calculation........................................................................................................................ 115 Ripple................................................................................................................................. 115 Two-stage filter............................................................................................................... 116 8.3 Regulation with a feedback loop .................................................................................. 116 8.4 Project: Adjustable constant current source .........................................116 9

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 6

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Customization................................................................................................................. 118 Syntax: Bitwise operators.......................................................................................... 119 Sketch: Adjustable constant-current source ....................................................... 120 Calibration......................................................................................................................... 125 8.5 Project: Lithium-ion battery testing and charging station ................127 Construction on a PCB................................................................................................. 128 Construction using thumbtacks ................................................................................ 129 Supplying power via USB ............................................................................................ 132 Separate power supply................................................................................................ 132 Cooling............................................................................................................................... 133 Sketch: Lithium-ion testing and charging station ............................................. 134 Current and voltage specifications.......................................................................... 149 Serial output.................................................................................................................... 151 Internal resistance........................................................................................................ 152 Calibration......................................................................................................................... 153 8.6 Project: Adjustable current source with limits ..................................... 155 Time vs charge amount............................................................................................... 155 Sketch: Adjustable current source with limits ....................................................157 Power supply................................................................................................................... 158 Serial output..................................................................................................................... 158 Cooling............................................................................................................................... 159 Default values, limits.................................................................................................... 160 Calibration......................................................................................................................... 161 Chapter 9 • Controlling motors ....................................................................................163 9.1 DC motors.......................................................................................................... 163 9.1.1 Transistor control............................................................................................... 163 9.1.2 Speed control using PWM ............................................................................... 164 9.1.3 Forward and reverse with an H-bridge ...................................................... 165 The L9110S............................................................................................................ 165 The L298N.............................................................................................................. 166 9.1.4 Full control using H-bridge and PWM ......................................................... 167 Syntax: min() and max() functions............................................................ 168 Sketch: Full motor control.............................................................................. 168 9.2 Stepper motors................................................................................................ 170 9.2.1 How it works........................................................................................................ 170 Bipolar and unipolar versions........................................................................ 171 Full- and half-step operation......................................................................... 172 Actual stepper motors...................................................................................... 173 9.2.2 The 28BYJ-48...................................................................................................... 174 Control using a ULN2003 driver board .......................................................175 Control using 4 transistors ............................................................................. 176 Tip: Stepper motor under battery operation ........................................... 177 Sketch: 28BYJ-48 stepper motor control.................................................. 177 10

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 7

2022-07-27 20:20

Table of Contents

9.2.3 Control using the A4988................................................................................. 183 Pinout...................................................................................................................... 184 Adjusting the current.......................................................................................... 185 9.2.4 Control using the DRV8825 ............................................................................ 186 Pinout...................................................................................................................... 186 Adjusting the current.......................................................................................... 187 9.2.5 Version A4988 vs. DRV8825.............................................................................. 188 9.3 Brushless motors.............................................................................................188 9.3.1 Control using ESC.............................................................................................. 189 Power supply........................................................................................................ 189 Control signal........................................................................................................ 190 Sketch: ESC-control using potentiometer ................................................ 190 9.4 Servos................................................................................................................. 192 Control............................................................................................................................... 192 Chapter 10 • Sensors...................................................................................................... 193 10.1 Analog sensors................................................................................................................. 193 10.1.1 Brightness sensor using LDR...................................................... 193 10.1.2 NTC temperature measurement .................................................194 Sketch: Temperature measurement using NTC...................................... 195 10.1.3 Analog joystick................................................................................198 10.1.4 Measuring light with a photodiode ........................................... 199 10.2 Digital measurements................................................................................................... 199 10.2.1 TL1838 or VS1838B infrared receiver......................................199 10.2.2 HC-SR04 ultrasonic distance sensor .........................................201 Syntax: pulseIn() function............................................................................. 202 Sketch: Ultrasonic distance measurement ............................................... 202 10.2.3 HC-SR501 motion sensor .............................................................205 Supplying power to the HC-SR501.............................................................. 207 10.2.4 The I²C interface.............................................................................207 SCL and SDA......................................................................................................... 207 I²C on the ATmega328 and 168................................................................... 209 Syntax: Including libraries............................................................................. 209 Syntax: I²C functions with Wire.h............................................................... 210 I²C sensors........................................................................................................... 211 Breakout boards................................................................................................... 211 10.2.5 BMP180 air pressure sensor....................................................... 211 Project: Pressure and altitude sensing with the BMP180 ................... 212 Syntax: Function definitions.......................................................................... 213 Sketch: Air-pressure sensor and altimeter .............................................. 214 Accuracy from double-oversampling............................................................... 219 10.2.6 MPU-6050 accelerometer.............................................................219 Sketch: Rotation and acceleration measurement.................................. 220 Output window...................................................................................................... 222 11

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 8

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

10.2.7 HMC5883L magnetic field sensor .............................................. 223 Project: 3D compass......................................................................................... 223 Sketch: 3D compass......................................................................................... 224 Output window...................................................................................................... 227 10.2.8 GY-87 multi-sensor......................................................................................... 227 Chapter 11 • Other components..................................................................................228 11.1 RF remote control .........................................................................................228 Coding................................................................................................................................ 229 Antenna............................................................................................................................. 229 11.2 Seven-segment displays.............................................................................230 Multiplexing...................................................................................................................... 230 11.2.1 Basic program for 1 to 6 digits ...................................................232 Sketch: 7-segment display with several digits ....................................... 233 int, float, hex, and degree displays ............................................................ 239 Syntax: modulo operator................................................................................ 239 Sketch: 7-segment display functions......................................................... 239 11.2.2 Project: Voltmeter.......................................................................... 244 Sketch: Voltmeter with 7-segment display ..............................................245 11.2.3 Project: Thermometer...................................................................246 Sketch: Thermometer with 7-segment display ......................................247 Thermostat............................................................................................................ 249 11.3 Text displays with back-lighting..............................................................250 Pinouts and functions................................................................................................... 251 Syntax: Controlling text displays ............................................................................ 252 Sketch: Example with user-defined characters ..................................................253 Text display with I²C interface..................................................................................... 254 11.4 Mini lasers....................................................................................................... 254 Laser application examples........................................................................................ 255 11.5 SD card module............................................................................................. 256 Connection to the Arduino.......................................................................................... 256 Syntax: SD.h file functions........................................................................................ 257 Sketch: Reading and writing files ............................................................................ 257 Chapter 12 • Rechargeable batteries and accessories .........................................260 Tip: Soldering round cells...................................................................................................... 261 12.1 Functionality and handling .......................................................................................... 262 12.2 Protection circuit............................................................................................................. 262 12.3 Connecting rechargeables in series ......................................................................... 263 12.4 Balancers............................................................................................................................ 263 12.5 USB charging regulators.............................................................................................. 264 Chapter 13 • Clever hacks and tricks.........................................................................265 13.1 Measuring battery level without components .....................................265 12

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 9

2022-07-27 20:20

Table of Contents

A weird measurement method................................................................................. 266 Sketch: Measuring battery voltage without components ............................... 266 Calibration......................................................................................................................... 268 13.2 Arduino in deep sleep..................................................................................268 Sketch: Sleep mode (bare template)..................................................................... 269 A pin to wake up............................................................................................................ 269 Sketch: Sleep mode (with wake-up pin).............................................................. 270 13.3 Low-battery switch-off...............................................................................271 Sketch: Low-battery switch-off................................................................................ 272 Integrating low-battery switch-off into projects ..................................................... 273 13.4 Pro Mini battery operation.........................................................................274 Reducing current consumption.................................................................................... 274 13.5 Project: Electronic die.................................................................................275 Syntax: EEPROM functions......................................................................................... 277 Sketch: Electronic die.................................................................................................. 278 Tip: LED effect board as a die.................................................................................. 285 Dice for cheaters............................................................................................................ 285 13.6 Analog measurement without waiting...................................................285 Sketch: Continuous analog measurement ........................................................... 286 Usage.................................................................................................................................. 289 13.7 Project: Universal remote control receiver..........................................291 Turning the principle on its head ............................................................................. 291 Sketch: 10-channel universal remote receiver .................................................. 294 Teaching the receiver..................................................................................................... 302 Tip: Exact clocking of the loop with one byte ..................................................... 304 Tip: Exact clocking of the loop using an integer ................................................ 305 Tip: Clocking of the loop with lateness options ................................................. 306 Tip: Clocking of the loop using only system time ............................................. 307 13.8 Project: Extreme altimeter........................................................................ 308 Sketch: Extreme altimeter......................................................................................... 308 Settings and possibilities............................................................................................... 312 Measuring small altitude changes........................................................................... 312 Weather trend barometer........................................................................................... 313 13.9 Project: Infrasound recorder....................................................................315 Sketch: Infrasound recorder..................................................................................... 318 Weather recorder........................................................................................................... 325 Index.....................................................................................................................................327

13

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 10

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Chapter 1 • ATmega boards The ATmega328P from Atmel is one of the most popular Microcontrollers for all applications that don’t require a lot of computing power. RAM, ROM (i.e. EEPROM), as well as processor and I/O connections are integrated in a little chip, making up a standalone computer that can be programmed using a USB cable or adapter connected to a PC.

Fig. 1a: ATmega328P

Fig. 1b: An Uno board, 3 different Pro Mini boards, a LilyPad and a Nano The picture shows different boards using the ATmega328P. Each has a quartz crystal for generating its clock signal. Most have a voltage regulator to supply their chips with a clean, regulated power source (5 V or 3.3 V). The Arduino Uno and Arduino Nano boards also have an integrated USB interface, while the Pro Mini and LilyPad boards require separate USB adapters.

1.1 The Pro Mini form factor The Pro Mini board is our choice for most of the projects in this book, as it’s available from different manufacturers with only minor differences, and it’s very affordable. It’s very small and has everything that such a board requires. It doesn’t have a USB interface. Because you use that port only to upload your completed programs to the board, it’s wasteful to have it on every board only to be sitting there unused in the completed project. Instead, we use a separate USB adapter as the necessary interface, which we can reuse for any of our other boards. The software can be modified and updated at any time simply by plugging in the adapter and connecting it to our PC.

14

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 11

2022-07-27 20:20

Chapter 1 • ATmega boards

A computer for a few euro With its small form factor and omission of the USB interface, the Pro Mini board is astonishingly cheap. Nevertheless it’s everything built-in, that you need, from processor to EEPROM – a full-featured computer ready to be programmed for measurement and control. Directly from China, you could get them a few years ago for under 2 euro. Since then, the prices have risen occasionally.

Fig. 1.1a: Different Pro Mini boards

Figure 1.1a shows different Pro Mini boards available directly from China. They usually come with the necessary pin headers. There are generally 2×2 (i.e. 4) different versions, as can be seen in the following table:

ATmega328P 32 kB Program memory 2 kB RAM 1 kB EEPROM

ATmega168PA 16 kB Program memory 1 kB RAM 512 B EEPROM

5 volts 16 MHz

Standard version for projects with mains power

Version for simple projects with mains power

3,3 volts 8 MHz

Suitable for batteryoperated projects

Suitable for simple battery-operated projects

15

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 12

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

5 V / 16 MHz and 3.3 V / 8 MHz versions The standard version has an ATmega328P microcontroller running on 5 volts at a 16 MHz clock frequency. If you only have a minimal source of power, you can opt for the 3.3-volt version, which is only clocked at 8 MHz and thus runs half as fast. The reason is that the microcontroller needs at least 4 volts to run at 16 MHz, and can even run at up to 20 MHz on a 5 V supply. The microcontroller’s direct supply voltage is normally labeled VCC. Accordingly, the 16 MHz versions have a 5 V regulator on board, while the 8 MHz versions are 3.3 V. The RAW input voltage to the regulator may be as high as 12 V. To keep the regulation as efficient as possible, it’s best to have a voltage that’s marginally higher (ideally a maximum margin of 3 V) than the regulated output voltage (the 5 V or 3.3 V). That means, for example, a 6 V supply for the 5-volt version, and a 5 V supply for the 3.3-volt version.

ATmega328P and ATmega168PA Each voltage version also has two microcontroller versions – the ATmega328P and the ATmega168PA. They’re identical, apart from the fact that the 168 has half as much RAM, half as much program memory, and half as much EEPROM storage. For less ambitious applications, this is more than adequate, and allows one to save a few cents by using the ATmega168PA for most projects. Generally, however, we could also just use the ATmega328P. For the sake of simplicity, I’ll dispense with the suffixes (“P” and “PA”) from here on – “ATmega328” and “ATmega168” are clear enough.

Connections The following abbreviations are used to identify the individual connections: RAW: The input to the voltage regulator, which can be as high as 12 V. From this, the microcontroller’s actual operating voltage, VCC, is created. GND: Supply voltage negative, i.e. ground. RST: Reset pin. This is tied to VCC via a resistor. The Reset button connects this input to ground and causes the chip to reset. VCC: The microcontroller’s operating voltage – usually 3.3 or 5 volts. 0 – 13: The digital inputs and outputs. 0 and 1 also serve as serial TX and RX. A0 – A7: Analog inputs. A0 to A5 can also be used as digital pins. 16

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 13

2022-07-27 20:20

Chapter 1 • ATmega boards

Pin layouts Another difference between Pro Mini boards is in the positions and layout of the connection pins. Fortunately, the variations are limited. Here are a couple of popular examples:

Fig. 1.1b The pin layout for the upper and lower rows is identical for all Pro Mini boards. On the right side, the connections (seen here with a pin header attached) are for the serial-toUSB adapter. The analog inputs, A4 to A7, are on the left side of this board.

Fig. 1.1c Here, pins A4 to A7 are located on the inner part of the board. The rest of the pinout is identical.

17

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 14

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Fig. 1.1d Here, note that the pins for the serial port (right) are reversed. The adapter must thus be connected the other way around.

Fig. 1.1e In this example, the serial port pins are also reversed. On the left, adjacent to pins A4 to A7 are a few more pins, but these are already available on the bottom row. MOSI, MISO, and SCK (identical to Pins 11, 12, and 13) can serve as an SPI bus if required. (This is a different kind of serial port, which we’ll discuss on page 256.)

1.2 Uno versions For the ATmega328P, there are also larger boards. The best-known is the Uno, and there are many variations of it, such as the original Arduino Uno Rev3 and a plethora of other Uno-compatible boards. Elektor even has its own Uno board, the UNO R4, that, with its ATmega328PB variant of the chip, has additional timers and other features. 18

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 15

2022-07-27 20:20

Chapter 1 • ATmega boards

Fig. 1.2: Different Uno boards Instead of male pin headers, the Uno boards have female header sockets for the individual pins. This is very practical for adding various peripheral expansion “shields” that are available for the Uno series. For us, however, these headers are sometimes a disadvantage. In any event, all of these boards may be used for the projects in this book, as long as you have access to at least 5 volts. For battery-powered applications, running at 8 MHz on 3.3 V is more appropriate.

1.3 LilyPads and similar These boards are optimized for lowpower, battery-operated devices, especially those with lithium-ion batteries. These boards save power, not only through their 8 MHz clock frequency, but also because they dispense with the on-board voltage regulator completely. Even a power LED, which serves no purpose but to indicate that the circuit is powered (while itself consuming power), is notably absent.

Fig. 1.3: The LilyPad

Running at 8 MHz with no voltage regulator, the ATmega328 can operate on between 2.7 V and 5.5 V. This is ideal for lithium-ion batteries, which deliver around 4.2 volts when fully charged, and about 2.8 V when empty. They should not be drained any further than that. 19

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 16

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

A degree of battery protection can be achieved by using the ATmega’s standby mode when the battery is almost empty. Then, only a few μA are used (i.e. practically nothing). A more in-depth explanation is given in Chapter 13.3, on Page 271. Even the inexperienced solderer will get familiar with the LilyPad quickly. The clearly-laid-out, large connections invite one to practice. LilyPads can be obtained directly from China for around 3 euro.

16 MHz LilyPads Officially, LilyPads operate at 8 MHz, but that doesn’t bother some Chinese manufacturers, who now prefer to offer 16 MHz LilyPads. For applications that need high speeds, this may be optimal, but usually the higher clock frequency is a drawback. The current consumption is higher, and thus, according to the datasheet, the microcontroller needs at least 4 volts to work at 16 MHz. We might be able to get by with about half a volt less, so these versions can also be run on batteries, but with restrictions. When we upload our programs, we have to ensure that the Arduino IDE is aware of LilyPads. For this, we must select a Pro Mini board and then specify a clock frequency of 8 MHz. This is important, otherwise serial ports and delay functions, for example, will run at double speed.

1.4 The Nano board The Nano is similarly compact to the Pro Mini, but has an integrated USB interface. A CH340 chip is found underneath the board, enabling an interface between the serial port (RS-232) and the USB connector. The Nano offers one advantage over the Pro Mini: The ATmega328’s analog reference input is available at the pinout, labeled “AREF.” The Uno also has this pin, while the Pro Mini and LilyPad boards lack it. Fig. 1.4: Nano board The USB interface described in the next chapter is already integrated in the Nano board.

20

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 17

2022-07-27 20:20

Chapter 2 • USB adapter with serial interface

Chapter 2 • USB adapter with serial interface In contrast with the Uno and Nano boards, the Pro Mini and LilyPad boards have no USB connectors, so we need an appropriate adapter, which is only plugged in when we need to upload our software.

Fig. 2: Two different USB-to-serial adapters While the program is running, it’s also possible for the board to send serial data, which can then be monitored in a window on the PC (using the so-called “Serial Monitor”). This is often useful for debugging purposes. The program still runs without the serial connection, but the data is simply sent into the void. Additionally, such an adapter can also be used to supply power to the board, but a regular USB cable (without the serial interface) can serve the same purpose if the power is to be supplied via USB. All of these adapters (or converters, as it should be) have a special IC that enables the conversion between USB and traditional serial protocol. This is like the standard RS-232 interface, but at logic levels of either 5 V or 3.3 V. These are often called UARTs. The most commonly-used ICs for the purpose are the CH340, the PL2303, and the CP2102.

2.1 USB adapters based on the CP2102 I would recommend the converter based on the CP2102. It costs a few cents more, but experience has shown that it works reliably, without driver issues. It also works on any PC USB port. (Other converters sometimes require changes to the port settings when you plug them into another port.) The CP1202 is identifiable by its square shape. Most of the other commonly-used chips are more rectangular. Fig. 2.1a: CP2102 21

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 18

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Another advantage offered by this adapter is the DTR connection, which we can make good use of. One should pay attention to this when purchasing – the most versatile converter will have the following 6 connections: DTR RX (or RXD) TX (or TXD) +5 V GND (minus or ground) +3,3 V Fig. 2.1b: Serial adapter based on the CP2102 Direct from China, these adapters often cost less than one euro. There are versions with large standard USB connectors, which one can plug directly into a desktop or laptop USB port. Others have a Micro USB port, which require the use of a Micro USB cable. These are suitable for permanently connecting an adapter to the Pro Mini. The USB cable then serves as an interface you can plug into the PC. If the adapter is only needed for uploading programs to the board, then I prefer to get rid of the unnecessary additional connectors (via the USB cable) and instead opt for the adapter with the larger standard USB-A connector, which can easily be used as a pluggable adapter cable, as in the project that follows.

2.1.1 Project: Universal serial adapter cable Before we can begin with Arduino projects, we need a USB adapter. Important criteria: A large, standard USB-A connector, CP2102 chip, 3.3 V and 5 V connection as well as another connection pin, which is usually labeled “DTR.” (Of course we also need the GND, TX, and RX pins). With some wires and a few small components, we can create an optimal universal adapter cable.

Construction

Fig. 2.1.1a: The necessary parts

We need: • • • • • • • • •

1 2 2 2 2 2 1 2 1

USB-to-serial adapter (CP2102 chip) meters black wire (appr. 0.14 mm2) m red wire (appr. 0.14 mm2) m yellow wire (appr. 0.14 mm2) m green wire (appr. 0.14 mm2) m blue wire (appr. 0.14 mm2) pin header, 6-way (e.g. BL 1 6 G) jumper cables (each 1-pin, female) heat shrink tubing (2.4 / 1.2 mm)

22

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 19

2022-07-27 20:20

Chapter 2 • USB adapter with serial interface

The red and black wires are important. Instead of yellow, green, and blue, one may opt for other colors; all that matters is that all 5 colors are clearly distinguishable from each other. The wire lengths are also up to you – I would use at least 1 meter. The signal still comes through clearly at lengths of up to 3 meters. In order to bundle them into one, neat cable, braiding is a good method, but the complete cable will then end up being a bit shorter than the individual wires.

Fig. 2.1.1b: Adapter connections and wiring Figure 2.2.1b shows the adapters’ wiring. The dashed lines have no fixed, soldered connections, but can rather be plugged into the USB adapters later. For example, one could switch the VCC wire between 3.3 V and 5 V. Once the 5 wires have been cut to the same length, it’s best to start on the side of the board with the 6-pin socket that will later be plugged into the Pro Mini’s pins. For this, a BL 1 6 Z connector is suitable, but the higher-quality BL 1 6 G is even better, as it has gold-plated contacts. Since such connectors tend to melt or warp during soldering, moving the contacts, I highly recommend connecting each female socket to its male pin counterpart before soldering (the male connector may even be significantly longer with more contacts) to keep everything in place. Now, the wires’ ends are stripped to about 2 mm (not longer than the socket’s solder connections), and then soldered into place.

23

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 20

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

 Tip: Neat soldering After stripping, the threads should be twisted gently by finger, so that no strands are sticking out. Then, the wires can be tinned with the soldering iron and a small drop of fresh solder. Important: Always put the soldering iron at the soldering joint first. Only then do you touch the solder to the soldering joint (or on the border between soldering iron tip and solder joint), rather than to the soldering tip alone, as the solder is supposed to melt and spread out at the solder joint rather than just spreading all over the soldering tip. It’s completely wrong to first touch the solder to the soldering iron and then introduce both to the area you wish to solder. Similarly, contacts, pins or solder lugs are always tinned with a little fresh solder at first, because only the flux within the solder causes it to spread along and adhere to the metal surface. However, the flux evaporates quickly, so you need to use fresh solder for each application, regardless of whether there’s solder hanging from the tip. Rather tap or wipe the tip off occasionally. Most soldering stations have steel wool or a sponge for the purpose – the latter should be moistened for the purpose.

Once the wires and sockets are tinned, the connectors should be fixed in place somehow (e.g. using a weight or a clamp), so that the soldering area is easily accessible. Before that comes a small piece of heat shrink tubing (somewhat longer than the pins to be soldered).

Fig. 2.1.1c: Soldered; loose heat shrink

Now, we have 6 contacts, but only 5 wires. This is because the black ground wire (GND) is connected to the first two pins. The best way to handle this is to hold the wire between the two pins and apply enough solder to create a large solder joint between the two Pins.

Ensure that the heat shrink tubing is far enough away when soldering, so that it doesn’t shrink right already. The rest of the wires can be soldered to the corresponding connector pins. The wire after the black is the red, which is soldered to Fig. 2.1.1d: Heat shrink shrunk the “plus” connection, and then the remaining three colors. When all the wires are soldered, the heat shrink sleeving is slid down over the soldered connections, and shrunk firmly into place. For this, one may hold each side of the connector assembly briefly over a cigarette lighter flame.

24

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 21

2022-07-27 20:20

Chapter 2 • USB adapter with serial interface

Now, we can braid the wires. To do this, the connector must be fixed, preferably on a table edge, so that you can tug gently on the wires. With 5 wires, there are several ways of proceeding: I always grab the outer-left and outer-right wire alternately and place them over the two wires immediately adjacent to each of them, toward the middle. Once a piece has been braided, use your fingers to separate the rest of the wires in the unbraided cable remaining. This is, unfortunately, a bit tedious when the remaining cable is still quite long. When the entire cable is braided, leaving only a few centimeters remaining, fix the braid with a suitable clamp, as in the image on the right, so that nothing can come loose. This can also work with an ordinary clothes peg. Individual longer wires can be trimmed a little at this point. Fig. 2.1.1e

Fig. 2.1.1f: Clamp

Now, the individual wires are soldered to the USB adapter. Note: Don't tin all of the pins, as the red “plus” wire and the DTR wire are only connected when in use, not soldered. The RX and TX cables must be crossed over; that is, the wire that goes to RX on the other end of the cable must go to TX on the adapter side, and vice-versa. (There may be another letter after the RX and TX abbreviations, but we can ignore these.) For the black ground wire, there’s only a single pin on the adapter side. Note: Don’t forget to put the heat shrink tubing on the wires before soldering! Now, only the “plus” wire and the DTR wire remain. These we will make connectable. For this, we’ll solder the ends of single-pin header sockets from jumper wires. Best to use jumper wires with the same colors (so, red, and the color you used for the DTR wire). We cut the jumper wires about 3 cm from the connector. Then, we strip about Fig. 2.1.1g: Soldered onto the header pins 3 mm of each wire, making sure that we add heat shrink tubing to each wire (about 5 mm long), tin the wires and solder them to each other – i.e. each of the remaining two wires gets a socket.

25

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 22

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Usage

Fig. 2.1.1h: Adapter cable, fully soldered Depending on the board in use and the required operating voltage, the red “plus” wire must be connected either to the 3.3 V pin or the 5 V pin. Should the board be supplied with some other source of power, the red wire is not connected at all. The DTR wire is needed so that the board can be reset automatically when required. When uploading a program, the board must be reset at the correct point at the beginning of the upload. One can also do this manually, by holding the Reset switch and letting it go at the right point in time, but it’s much simpler to let the DTR wire handle this automatically. Should you need to use the USB in the application, e.g. to send data from the board to the PC (once the board has been programmed with your application), it’s best to disconnect the DTR wire. In this way, accidental reset can be avoided. The power supplied by the red wire is only needed if the board is not otherwise supplied with power (e.g. via the board’s RAW input).

2.1.2 Serial Micro USB adapter This USB adapter is useful for when the USB interface needs to be connected to the Pro Mini board for long periods of time, for example in applications that work with the PC and data is output, or if the board must be supplied with power using the USB connector. Connection to the PC will then be done using an ordinary Micro USB cable.

Fig. 2.1.2 PC2102-based Micro USB adapter

One may also make use of the Nano version, which has such a converter built in (although it makes use of the CH340 chip). 26

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 23

2022-07-27 20:20

Chapter 3 • Buying tips

Chapter 3 • Buying tips For microcontrollers and other components that we’ll need here, there are, unfortunately no stores just around the corner that you can pop in to. Here, almost everything is done via mail order. With online ordering, the world is open to us, with enormous possibilities and opportunities, but also with some traps and pitfalls that we’ll discuss here. In this chapter, I’d like to offer some tips and suggestions for optimal component purchases in order to save money and avoid problems. I’m independent, so I don’t get anything in return from any of the companies mentioned below. In today’s digital world, however, many things can change at any time. Therefore, please understand that, as an author, I can’t guarantee all information, but I do want to pass on my extensive experience in this area. Prices also can change at any time. In 2017, for example, I actually bought some ATmega328-based Pro Mini boards directly from China for 1.03 euro. Since then, the prices have spiked again, for now. Therefore, the information on prices in this book can only serve as a rough guide.

3.1 Local suppliers and domestic mail order companies In many countries, mail order companies were known to sell to their own country, predominantly. Some of them are older than the internet. In the past, they sent out catalogs of various thicknesses regularly, and people ordered by phone, or even by postcard. That’s how it was done in the last century. Today, of course, all of the major mail order companies have online stores. In big cities, there are usually electronic stores that offer ranges of electronics with varying levels of comprehensiveness. All these offerings are naturally different in every country. Nevertheless, I would like to discuss some of them, especially those that have also established an international trade, and are known beyond the country's borders.

3.1.1 Conrad Electronic Conrad is a German company that has been around for a hundred years. It’s a very large supplier of electronic components with the widest range of products in Germany and meanwhile also internationally known. However, this diversity comes with a cost – literally. Also, despite the large selection, some of the lower-priced components are harder to find, while you can find others but at several times the price offered by other retailers. Therefore, I cannot recommend Conrad Electronic, unfortunately. 27

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 24

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

3.1.2 Reichelt Elektronik Reichelt is also a German supplier, which today also sells internationally. In the offer are many standard electronic components, stranded wires, consumables, etc. The range of products is nowhere near as large as at Conrad, but the prices are usually quite reasonable. There’s although no Pro Mini board to find at all. Some of the other components that we need for the projects in the book can be found there.

3.1.3 Other online suppliers There are several other suppliers in some countries, which I do not want to discuss in detail here. Most of them also sell internationally, many also to private customers. The prices often could be better, but it's also worth just browsing these sites. Therefore I want to mention them briefly here: Arrow Electronics   a US electronics distributor TME   an electronics supplier based in Poland Rutronik   another supplier from Germany Pollin Electronic   only German & Austrian websites, but lot of cheap remaining stock Lextronc   another supplier from France Cotubex   a supplier from Belgium (side languages EN, FR and NL)

3.2 Big International online stores With the spread of the internet, more and more online platforms have opened up that enable you to place orders worldwide. Some serve exclusively as a platform for external sellers, while others, such as Amazon, also offer a huge range of products themselves.

3.2.2 Ebay Ebay does not sell items itself, but is merely a platform for many dealers and private sellers. They’re located around the world, especially in China, and offer their products from there – that’s where we find the cheap Pro Mini boards and the other components we’ll need for our projects. Since the shipping is mostly from China, the delivery time may often be over a month, depending on your destination address. Most of the items can also be found at local dealers, but often at higher prices. 28

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 25

2022-07-27 20:20

Chapter 3 • Buying tips

Search settings If you type in a search on ebay.com, numerous settings appear above and to the left of the search results. These enable you to limit search results. Under “Item Location,” for example, you can often limit the search to items that are shipped from your own country or region, depending on your location. (Don’t confuse the location settings on ebay.com with the regional Ebay sites, such as ebay.de, ebay.co.uk, or ebay.com.au – these local sites show only items that are available for sale on them.) If you select “Worldwide,” items from other country sites will also appear, sometimes even in other currencies. You may also opt to use the local country sites as well. Also you can sort items by using the options right above the search results. The setting “Lowest price incl. shipping” makes sense if you’re ordering only one item. If you need to have 3 or 5 Pro Mini boards in stock, it’s best to sort by lowest price (without shipping). Then, take the resulting shipping costs into account when comparing. There are countless other search settings, which I won’t go into individually here, except to say: You can also click on “Advanced” to the right of the “Search” button, and get many additional search options.

Security on Ebay Since you don’t know the sellers on Ebay, having comprehensive buyer protection is important. However, you only get this on Ebay if you pay using PayPal. This payment service acts as a trustee. If the goods don’t arrive, are defective, or don’t match their descriptions, you can file a “Case” and claim Buyer Protection.

3.2.3 Amazon In contrast to Ebay, Amazon is not merely a platform for other sellers. Amazon also sells a lot of products itself. Many items available there can be purchased directly from Amazon, as well as from other sellers. A lot of the sellers store their products at Amazon warehouses, make use of Amazon’s logistics, and Amazon takes care of the shipping. As with Ebay, there are also many Chinese sellers who ship their goods directly from China. Once again, for the microcontroller boards and other components we need, these dealers usually offer the lowest prices. The downside is the lengthy shipping times you can expect from China. There are also black sheep among Amazon’s sellers, but, as a customer, you are still on the safe side, as Amazon acts as a trustee (much like PayPal). Valid complaints are almost always dealt with without a hitch. 29

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 26

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

3.2.4 AliExpress AliExpress belongs to the Chinese Alibaba group, and is a gigantic platform for international trade – it’s like a Chinese version of Ebay. Here, we can find microcontroller boards, sensors, and other components in huge quantities and at the lowest prices you’ll find. I order almost everything from AliExpress, even though the goods often take over a month to arrive. On the site, you can select different languages, but the site works best in English. Communication with the sellers (if it’s at all necessary) is in English as well. Searches on AliExpress can be a bit tricky. Most of the time, hundreds or thousands of items will come up, most of which will disappear again when you sort by price. Sometimes it helps to use different search terms. However, you have to select your sort criteria after each search. Often, narrowing the search by using additional terms does not result in fewer search results, as one would expect, but many more. If you click on an offer that you found, it’s worthwhile to check right at the bottom of that product’s page, at the “Seller Recommendations” and “More To Love” sections. Often, the item you’re searching for can be found even cheaper there.

AliExpress shipping costs Years ago, you could order many electronics parts from China on AliExpress for less than one euro including shipping. That’s incredible when you consider that domestic shipping alone (not including the value of the goods) often costs significantly more in most countries. However, those times are over. While small, light goods still benefit from moderate shipping costs, heavier goods (for example, speakers) are usually not worth it.

Buyer Protection on AliExpress As with the other online stores, AliExpress offers buyer protection to customers. A few years ago, this was merely a bad joke. Even with clearly valid complaints, you’d be required to provide photos, videos, etc., several times as evidence. As a buyer, you often spent an hour of your time just to get 2 euro refunded. This has changed significantly. With today’s buyer protection, the bad joke is now an insane joke. By this, I mean that, even if you read in the tracking that your package never left China, AliExpress decides in favor of the seller, with the terse remark that the goods have been delivered, and even if a seller cheats and sells a completely useless product, at best, you’ll get the right to send the goods back to China at your own expense, which, from most countries, usually costs more than the goods did. 30

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 27

2022-07-27 20:20

Chapter 3 • Buying tips

Unfortunately, there’s no defense against this at all. There’s an appeal function against dispute decisions, but you won’t achieve anything with it. Further, there’s no way to enter into a dialogue with AliExpress. You can chat with their “Eva” service, but it turns out to be just a primitive bot – you’d have better luck talking to a slice of toast. However, there’s a way out: AliExpress now offers PayPal payments, so you can make use of PayPal’s buyer protection. The important thing is that you file your claims with PayPal, not AliExpress. Without this protection, I would strongly recommend against buying from AliExpress. With it, I can still recommend AliExpress, as most of the merchants there are still reputable, and the prices are unbeatable.

3.3 PayPal payment service As already mentioned, PayPal acts as a trustee service for online payments. The money is retained for a short while so that it can be awarded to the favored party in the event of a dispute. Thus, PayPal’s buyer protection is often the only safe payment method available for online purchases. For online payments, I’ve been using PayPal exclusively for many years. Recently, however, PayPal’s buyer protection has become absurd when it comes to orders from China. Even in the case of a valid complaint, it’s happened that PayPal has insisted that the goods be sent back to China in order to get a refund. Initially, you have to pay the return shipping costs yourself, but PayPal offers to reimburse those costs (up to 12 times a year). The absurd part is that, even if the return shipping costs over 5 times a much as the entire order, this is the only way to do it in most cases, so PayPal would rather pay 5 times as much (from its own pocket) than simply granting the refund. Alongside the business transactions, PayPal also offers a way to pay small amounts to private individuals as a means of cashless payment. For example, if you’ve lent a friend money or paid for something for someone, it can be repaid quite simply via PayPal. There, it will stay in the user’s account until it’s spent again. Importantly, you have to distinguish between these two payment types on PayPal. Payments with “PayPal Buyer Protection” when you’re paying for goods require a small fee, but the buyer won’t notice it, because it’s paid by the seller. There’s also the option to “Send Money to Friends and Family.” For this, there’s no fee at all, but there’s also no buyer protection. Therefore, as a buyer, you should always decline the latter payment method unless you know and trust the seller one hundred percent.

31

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 28

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

3.4 Customs Whether import duties are incurred depends on where you buy from and where the product is shipped. Worldwide, there are several common markets with customs unions (e.g. the EU) within which no customs duties have to be paid. For orders from China, this is often different. To ship to the EU, for example, there are customs fees or orders of over €150, but, even for smaller orders, the VAT applicable in the recipient country may be charged. For other regions in the world, other regulations apply. You should inquire about these in your country. Often, however, no fees are charged for small orders.

3.5 Caution: Pitfalls! Even if you pay using PayPal, be aware that there are still some risks. If the merchant tries to undermine the buyer protection, or cheats in a way that you don’t even notice it, buyer protection won’t help.

Fake items It’s become extremely difficult to buy cheap memory cards and sticks on the internet, because (sorry to be so blunt) China has been flooding the world with fake memory cards and sticks for several years. If you look for a larger memory device (over 100 GB) on AliExpress or Ebay, and you buy the cheapest one, you’ll most certainly get a worthless, fake device. Yet, they will still have seemingly good ratings. How is this possible? It’s a very deceitful scam, which the buyer will not even notice. The cards contain only slow, low-quality memory chips of 8, 16, or max. 32 GB, but will appear to show up having many multiples of this. When the buyer tests the card by loading a few gigabytes onto it and then checking it, he’ll be quite satisfied, because the card appears to work fine. At most, it may be noticeable that the card is a bit slow. When you fill the card with data, it still seems fine, as the card will let you save as much data on it as it pretends to hold. But, here’s what buyers don’t expect: Only a few gigabytes will exist at a time. The remaining data will contain only garbage, will be overwritten, or will simply be dispensed with completely. However, this is only noticed after months. You find that the data is gone, but still you are not suspecting any fraud; you’re simply disappointed that the device has failed so quickly. Often, you may simply reformat the card, do some quick tests, and again it will seem like the card is working fine again, only to lose your data later again. 32

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 29

2022-07-27 20:20

Chapter 3 • Buying tips

Unlike Ebay and AliExpress, Amazon managed to steer clear of such fake cards for a long time. However, since 2021, one can find many fake products there. When using search terms such as “sd 1024 gb,” one occasionally finds hundreds of fake cards and very few genuine ones. Although Amazon has been informed of this many times, it took months until these offers were removed. In the interim, many more fakes appear. Therefore, I strongly recommend thorough testing of memory cards and USB memory sticks immediately after purchase. A small freeware program with an amusing name, “h2testw,” is your best choice. With it, you can write to and verify the entire available (free) memory area on any storage medium, with just a few clicks.

False information False information is often found in online offers of any kind. A particularly egregious example was with solder, which was offered as a 50 gram roll. It seemed a bit light to me, so I weighed it, and, lo and behold, it came to 31 grams, including the dispenser. Now I wanted to know exactly how much Fig. 3.5: Scam solder dispenser roll the solder weighed, so I unwound the entire roll. Conclusion: a double-walled scam dispenser roll weighing in at 20 g and only 11.5 g (instead of 50 g) of solder. Later, it turned out that the solder wasn’t even up to specification – it wasn’t usable at all. It's better not to buy solder directly from China also for another reason: It’s a relatively heavy product, so shipping is expensive; local dealers will usually be cheaper overall. The same applies to heavy cables and the like.

False promises When contacting sellers about products that aren’t in order or descriptions, many sellers (especially on AliExpress) react in an saying that they’re terribly sorry and that they will do everything satisfactory solution. In reality, they don’t budge an inch and will voluntarily.

don’t match their over-friendly way, possible to find a not refund a cent

When you subsequently file a dispute, they tell you how damaging this is to them as a merchant and implore you to cancel the dispute, after which you will get your refund. Instead, of course, you get nothing and lose your buyer protection instead. There really are sellers who make the same promise ten times without ever honoring their word. 33

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 30

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Of course, not all sellers are the same. I have specifically pointed out the dangers and warned against the bad actors, but you should not get the wrong impression. In most cases, you get good products at very reasonable prices, and I am very satisfied with the vast majority of my purchases.

3.6 Buying basic equipment When ordering from China, whether via AliExpress, Amazon, or Ebay, always bear in mind that delivery may take several weeks, so it’s a good idea to consider which projects you want to tackle in the next few months, and what you’ll need for them. For this reason, I recommend that the reader takes a quick look at the rest of the chapters and projects now in order to the components for everything you’ll want to build in the next few months. With the prices on AliExpress, it doesn’t matter if you use a particular sensor or not, when you’ve paid a few cents or a euro for them. Some dealers will offer many of the small parts that we need, without shipping costs rising sharply with each additional part. In extreme cases, you can get a hundred different parts delivered for the same price as a hundred pieces of the same part. So, for now, you need to have a basic set of tools, consumables, and parts so that we can get started with the upcoming topics and projects.

3.6.1 The necessary tools The basic equipment includes a soldering station, or at least a simple soldering iron, but it should not have more than 25 or 30 watts of power, or it will get too hot after some time. In addition, we need good solder (1 mm Ø) with flux core. Unfortunately, the best is the old type, consisting of almost 40% toxic lead, which should no longer be used today and which is also hard to get.

Project: The simplest soldering station in the world A low-power soldering iron is good for fine soldering work, but it won’t have enough power for large solder joints. A high-power iron, on the other hand, is too hot and coarse for fine work. The best choice is always a soldering station with adjustable temperature. There is, however, a simple DIY solution – a converted soldering iron, which we can switch between half- and full-power when necessary, with the help of a switch and a 34

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 31

2022-07-27 20:20

Chapter 3 • Buying tips

simple diode. That's very simple, but we are working with wires that will later have mains voltage. So one should already have some experience. Everything must necessarily be well isolated! It's best to use a simple soldering iron, preferably a small one with enough power, for example 40 watts. Then, we need an additional power cord (3-wire with electrical plug to plug into the mains). Simply cut the power plug off the soldering iron. The cable remains attached to it and is connected, as in Fig. 3.6.1a, via the components to the new power cable.

Fig. 3.6.1a: Switchable power-halving for soldering iron When switched to the low-power position, only a half-wave of the AC power will flow through the diode (1N4007), thus halving the power. In the high-power position, the diode is bridged by the switch. An ideal choice is a footswitch, as is used in freestanding lamps, or some other inline switch, such as one used on an electric blanket. The switch housing also has enough space to house the diode. With a three-position switch (0, I, and II below), one may switch the soldering iron between high and low power, as well as turn it off completely. Fig. 3.6.1b shows how this is done.

Fig. 3.6.1b: 0 – I – II - Switchable power-halving for soldering iron

Warning: The wires must, of course, be well-insulated, so that you cannot touch any of the contacts. After all, we are dealing with mains voltage here.

35

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 32

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Additional tools We’ll also need side cutters and a wire stripper. Fig. 3.6.1c shows two cheap options from China, which I like to work with. A small pair of needle-nosed pliers (possibly angled at the front), and a cutting knife are also useful. For components with screw contacts, of course, you’ll need a screwdriver.

Fig. 3.6.1c: Side cutter and wire stripper A hot glue gun is also very helpful, e.g. to affix wires and components, as long as they don’t get too hot. Larger transistors and resistors, which heat up a lot during use, will of course not hold using hot glue. Be careful with the very cheap offerings from China. These small hot glue guns, at about 3 euro, can supposedly be operated at anything from 100 to 240 volts, but in reality don’t really like mains voltages over 200 volts, and may surprise you with a spontaneous explosion, usually the moment you switch them on.

3.6.2 ATmega boards If you’re not just doing test setups, but want to create microcontroller projects, it’s good to have a few boards in stock. For starters, I recommend a few Pro Mini boards of the 5 V / 16 MHz variant with the ATmega328 microcontroller, and a few LilyPads running at 8 MHz, as these are optimally suited for battery-powered applications. One or two Nano boards can also be purchased in case you need the analog reference port for applications that communicate with the PC, and thus need a USB interface.

Serial adapters We mustn’t forget the serial adapter, which I’ve already described in Chapter 2. I recommend the universal adapter cable in section 2.1.1 on page 22. You’ll also find the detailed component list there. The converter should have a DTR connection. A single adapter suffices, but at the price (under €2 from China), it certainly doesn’t hurt to have a spare available. 36

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 33

2022-07-27 20:20

Chapter 3 • Buying tips

3.6.3 Power supply If the board is not to be powered via USB, or the completed circuit requires a higher voltage or current than can be supplied via USB, a power supply will be needed. On the other hand, if the device needs to be mobile, batteries or rechargeables will be required.

Mains power supplies What kind of power supply is needed depends on what we want to do for each project. To power only the Pro Mini board and perhaps one or two sensors or a few small LEDs, neither a higher voltage (than 5 V) or current is needed. Even a 5 V / 100 mA supply is sufficient. In other cases, the loads we want to drive (e.g. motors, power LEDs, etc.) determine the current and voltage required of the power supply.

The thing about current and voltage The power supply’s voltage must, of course, be in a range suitable for the components. For the RAW connection on the Pro Mini 16 MHz variant, it’s 5 to 12 volts, while on the 8 MHz variant it’s 3.3 to 12 volts. For components such as motors, lamps, etc., the nominal voltage may only be exceeded slightly at most. With a slightly lower voltage, the performance usually decreases a bit. Sensors and other small components can usually work on the VCC voltage generated by the board itself, when it’s supplied via the RAW pin. As far as current goes, all of the components must, of course, not consume more than the power supply can deliver – the board itself consumes just a few milliamperes, which is hardly significant. If the power supply can deliver more current than is required, that is not a problem. Novices often worry that if a supply that delivers more current than is required, it can break components, but only as much current will flow as the circuit requires. It’s too high a voltage that’s dangerous.

Fig. 3.6.3a: USB power supply 5 V max. 1 A

Fig. 3.6.3b: Power supply 5 V max. 2 A 37

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 34

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

In the end, it doesn’t matter whether you use a plug-in power supply, a power supply module, or a power supply board. On AliExpress, a few dealers sell power supply boards such as the one in Fig. 3.6.3b very cheaply. They come in different sizes and different voltage and current ratings. What they all have in common are the short cables at their inputs and outputs. Nonetheless, they’re new and very high quality, all short-circuit protected and have some SMD components on the undersides of the boards. Presumably, they’re from some over-production and may have been removed from new products. I happily use such power supplies and have never had any trouble with them.

Fig. 3.6.3c: Power supply 12 V / 3 A

Widely used and somewhat more expensive are power supplies such as this, available in many different voltage and current configurations. They’re also usually of high quality. You should use a power cable with a protective contact (green-yellow wire), which is connected to the middle of the 5 terminals, and grounds the sheet metal enclosure. The orange component next to the green LED is a small trimmer potentiometer for fine adjustment of the voltage (e.g. between 11 and 13 volts for a 12 V power supply).

Of course, you have to consider that mains voltage is applied to the input lines – in most countries about 230 volts. Caution must be exercised when using the bare power supply boards, as parts of the board are under mains voltage. If you don’t want to handle mains voltage at all, you can use such a power supply with closed enclosed and a fixed or plug-in power cord:

Fig. 3.6.3d: 12 Volt power supply, max. 5 A (2 A version also available, for example) 38

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 35

2022-07-27 20:20

Chapter 3 • Buying tips

DC connectors with an inner diameter of 2.1 mm and a 5.5 mm outer diameter are common. As shown in the picture, there are adapters with sockets on one side and screw terminals or cable sockets on the device side.

Disposable or rechargeable battery

Fig. 3.6.3e: 3 x AA

and

3LR12 flat battery

If you want to build portable, mobile projects using the 8 MHz Pro Mini or LilyPad boards, lithium-ion rechargeable batteries are the best choice. Alternatively, you could connect three regular 1.5 V disposable batteries (e.g. coin cells or AAs) in series. We then need a battery holder for the three batteries. It’s also possible to use one of the rarely-used 4.5 V flat batteries (type 3LR12). I generally recommend alkaline batteries. Zinc-carbon cells have a much lower capacity, so they go flat much quicker.

Lithium-ion rechargeables Of course, rechargeable lithium-ion batteries are preferable. They’re available in many conceivable sizes and designs. Best suited are the 18650 cylindrical cells, or the rectangular lithium-polymer cells, which are available any many different capacities and dimensions. More details about lithium-ion batteries and the handling thereof can be found in Chapter 12. (We’re only covering shopping tips here.)

39

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 36

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Fig. 3.6.3f: Different lithium-ion rechargeable batteries

Warning: Fake batteries There are also 18650 fakes from China that basically work and are usable, but deliver only a small fraction of the stated capacity – often below 1000 mAh. If you can manage with that, you can buy them. However, I’d only recommend it at a price of less than 1 euro per piece. The fake 18650s can often be recognized by the fact that capacities far in excess of 3500 mAh are advertised, which, even with today’s state-of-theart manufacturing, is not possible. Also, batteries with labels such as “GTF,” “GIF,” or, in former times Fig. 3.6.3g: Different 18650 fake batteries many “UltraFire” versions are usually fakes. A look at the ratings and reviews can also be helpful. Sometimes you’ll find that a buyer has tested the actual capacity and posted it. That's helpful, but even such a test is no guarantee.

40

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 37

2022-07-27 20:20

Chapter 3 • Buying tips

Charge controller with protection circuit This small board with a Micro-USB socket contains a charge controller for lithium-ion batteries, as well as an integrated battery protection circuit, all for under 1 euro. There are other versions with different USB sockets. There are also simpler versions without the battery protection, with a somewhat smaller board Fig. 3.6.3h: USB charger controller and only a single IC. I recommend the version with the protection circuit. It costs just a few cents more, and everything is integrated – charge controller and battery protection. To find these parts, it’s best to search AliExpress for “USB lithium.” More detailed information for both versions can be found in section 12.5 on page 264.

3.6.4 Standard components Regardless of the individual topics and projects, there are certain standard components that electronics hobbyists should always have on hand.

Resistors Standard resistors are usually rated at ¼-watt, and they’re available in countless different values in metal film as well as the somewhat cheaper carbon versions. They’re usually available cheaply from local electronic stores or mail order companies. If you have time to wait, you can also order them very cheaply from China. On these sometimes the connection leads are a bit thinner, but that is not of much consequence.

The E12 series For all of circuits in this book, we use only resistors with values from the E12 series, socalled because every 12 steps up represents a tenfold increase in resistance. Example:

1,

1.2,

1.5,

1.8,

2.2,

2.7,

3.3,

3.9,

4.7,

5.6,

6.8,

8.2,

10

After that, the series continues with 12, 15, 18, and so on. All in all, we make use of values from 22 Ω to 1 MΩ, but not all of them. The table that follows on the next page shows which resistors are used in the book. 41

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 38

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

12 Ω

15 Ω

18 Ω

22 Ω

27 Ω

33 Ω

39 Ω

47 Ω

56 Ω

68 Ω

82 Ω 100 Ω

120 Ω 150 Ω 180 Ω 220 Ω 270 Ω 330 Ω 390 Ω 470 Ω 560 Ω 680 Ω 820 Ω 1 kΩ 1.2 kΩ 1.5 kΩ 1.8 kΩ 2.2 kΩ 2.7 kΩ 3.3 kΩ 3.9 kΩ 4.7 kΩ 5.6 kΩ 6.8 kΩ 8.2 kΩ 10 kΩ 12 kΩ 15 kΩ 18 kΩ 22 kΩ 27 kΩ 33 kΩ 39 kΩ 47 kΩ 56 kΩ 68 kΩ 82 kΩ 100kΩ 120kΩ 150kΩ 180kΩ 220kΩ 270kΩ 330kΩ 390kΩ 470kΩ 560kΩ 680kΩ 820kΩ 1 MΩ Only the values printed in black are necessary for our projects. The orange values are needed for special settings, for example a voltmeter with a certain range of measurement. The values in gray, on the other hand, do not appear in the book at all. For current capacity, ¼ watt is sufficient. The tolerance should not be more than 1% (at least for resistors that serve as voltage dividers for measuring). Incidentally, there are resistor kits available that contain a wide range of E12 values. This is worthwhile, especially if you want to design your own projects. In addition, we need a few very-low-Ohm resistors that can handle more current. These are used for measuring current. It’s recommended to have a couple rated at 1 Ω / 2 W and a couple at 0.47 Ω / 2 W on hand. In this way, we can measure currents up to 1 A, and even a little higher. A very detailed list for many current ranges can be found in section 6.2.4 on page 78. In a couple of examples in the book, a potentiometer of 10 kΩ is used. Best to have one or two of these available. They’re often useful for setting analog values, e.g. to control a motor’s speed.

Capacitors Here, we need to distinguish between two different types: film capacitors and electrolytic capacitors. Electrolytic capacitors are typically used for larger capacities and it’s important to observe polarity when using them (i.e. the plus and minus connections must never be reversed). Again, I’ve compiled a brief list of the most important capacitors that you should have a few of in stock. Film capacitors: • 10 nF • 100 nF • 1 µF

63 V 50 V 35 V

Electrolytic capacitors: • 10 µF • 100 µF • 1000 µF

63 V 35 V 16 V

We get by here with very few types, each of which differ in capacity by a factor of 10. The two gray values don’t even appear in this book, but there’s no harm in buying a few of them as well. The maximum voltage rating is generous – more than we use. This provides some safety and also reduces leakage current, which is very relevant to battery-powered devices that need to run for a long time. 42

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 39

2022-07-27 20:20

Chapter 3 • Buying tips

LEDs As a simple indicator of whether something is on or off, as well as for gimmicks such as flashing lights, running lights, etc., you can use regular 5 mm Fig. 3.6.4a: 5mm LEDs LEDs in different colors. If you need it to be especially bright, and it is permitted to consume a bit more power, 1-watt LEDs in various colors are available cheaply from China.

Fig. 3.6.4b: 1W LED

• • • •

LED LED LED LED

5 5 5 5

mm mm mm mm

20 20 20 20

mA mA mA mA

red yellow green blue

• • • • •

LED LED LED LED LED

1 1 1 1 1

W W W W W

red green blue warm white cool white

The picture on the left shows a 1-watt LED with an aluminum heat sink and connection plate. You can get the LEDs cheaper alone, but these should be equipped with a mini heat sink or should not be operated at full power. Identical form factor LEDs are also available in 3-watt versions, where you have to pay even more attention to sufficient cooling. These LEDs are available in all colors, from infrared to ultraviolet, and even in unusual colors such as turquoise and in various shades of white.

I recommend having a few LEDs of each primary color on hand, at least for the 5 mm standard 20 or 30 mA LEDs. Similar ones are also available with 3 mm diameter.

Transistors A very good transistor for switching loads of up to 800 mA at 45 volts maximum is the BC337-40. As an electronics hobbyist, you should always have some of these in stock. If you need to switch higher currents, up to a maximum of 4 A, the BD435 is a good choice. With special MOSFETs such as the NTD4906N or the IRLR8726PbF, even higher currents can be switched easily. Detailed information about all of these transistors can be found in section 7.2 on page 99.

43

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 40

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Buzzer The design shown here is quite handy when used with the Pro Mini (and similar Arduinos), because it’s available as a 5-volt version and its power consumption is low enough that it can be driven directly from an Arduino output (i.e. without an additional transistor). Such buzzers are very useful for acknowledging, for example, the press of a button, with a short beep. Simple information can also be relayed, such as by varying duration and number of beeps. Even when running on 3.3 V (lithium-ion battery voltage), the 5 V version works very well, even if not quite as loud.

Fig. 3.6.4c: Mini buzzers

There are active and passive versions of this buzzer. With the active version, we simply apply a DC voltage for as long as we want it to beep. On the other hand, the passive version requires us to supply the necessary tone frequency. The active version makes control very simple, and the buzzer can be louder, because it beeps at its resonance frequency.

Jumper wires To connect individual pins on the pin headers (e.g. from the Pro Mini board to other components), these jumper wires are the simplest solution. You can separate these jumper wires individually or in groups. They’re available in various lengths and configurations, e.g. with male pins instead of female sockets at one or both sides.

Fig. 3.6.4d: Jumper wires

In principle, we could cut the wires in the middle and then solder them on, so that the connection can only be plugged and unplugged on one end of the cable. However, since copper is so costly, manufacturers also tend to use wires made of an aluminum alloy, which doesn’t accept solder. For permanent assemblies, however, soldered wires are better, and, if we want to make components pluggable, multi-pin connectors (such as described in section 4.6) are more stable and better than such single-pin connectors. There is also no problem with soldering, as we use stranded copper wire.

44

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 41

2022-07-27 20:20

Chapter 3 • Buying tips

3.6.5 Measuring tools Apart from tools and components, a multimeter is also a basic part of every hobbyist electronics engineer’s toolkit. Other measuring devices are useful, e.g. an infrared thermometer and a digital Vernier caliper. These can all be obtained directly from China for just a few euro.

Multimeter The DT-830 is probably the world’s best-selling multimeter, and has been for decades. It’s small, handy, relatively simple in design, and you can get one for under 5 euro. No, that’s not a joke! And, if you want to pay only half that, you can pool resources with friends and place a collective order. That wasn’t a joke either – think of vocational training classes, for example.

Fig. 3.6.5a: DT830B multimeter

There are many different versions of the DT-830, some with transistor tester, continuity beeper, thermometer, etc. Therefore, there’s always an additional letter at the end of the model number indicating the version. The picture shows the DT-830B as an example. The “D” version is also widely used. The model numbers sometimes exclude the hyphen, and some versions use the number 832 instead of 830.

Infrared thermometer If you occasionally work with power transistors or with ICs that switch larger power, you’re probably aware of the guesswork around how hot these components actually get – whether you need a (larger) heat sink, for example, or whether you could handle even more current. In such cases, a non-contact infrared infrared thermometer is very helpful. A small design, similar in size to a laser pointer, is totally adequate and quite practical. There are larger versions in pistol form that are somewhat more expensive, but not necessarily better.

Fig. 3.6.5b: Infrared pen-type thermometer

When purchasing, you have to be careful that you don’t get a version intended as a clinical thermometer, as these typically measure only a small range of temperatures. Best is to search for “mini infrared thermometer” on AliExpress. 45

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 42

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

To measure the temperature, hold the thermometer as close to the component as possible. Black components measure very well, but light surfaces (e.g. an aluminum heat sink) sometimes produce measurements lower than the actual temperature. To alleviate this, it’s useful to use a permanent marker to make a black mark on the component before measuring. Most of these thermometers perform the measurement once the measurement pushbutton is released.

Vernier calipers The simplest Vernier calipers are analog and made of plastic. There are now also inexpensive digital ones with displays. The simplest of these are also made of plastic, but for 10 euro, directly from China, you can get a high-quality digital electronic caliper made of stainless steel, with a resolution of a hundredth of a millimeter.

Fig. 3.6.5c: Digital electronic caliper

46

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 43

2022-07-27 20:20

Chapter 4 • Optimal construction

Chapter 4 • Optimal construction One question that every hobbyist asks at the outset of every project: What’s the best way for me to build it? There are generally several methods, which I’ll introduce briefly, each with its various advantages and disadvantages.

4.1 Construction on breadboard For a test setup, plug-in boards, so-called breadboards, are often used. They have many rows of holes into which components, cables, pins, etc. are inserted. Once inserted, the components are in contact with the contact row via the spring contacts underneath. In the image on the right, the contact rows, which are usually not easily visible externally, are highlighted in gray. Here, on either side, you can also see the long pairs of vertical rows marked with red and blue lines. These are usually used as plus (positive) and minus (ground) connections. Additionally, on the main part of the board are many short, horizontal, mostly 5-hole rows, on which the circuit is built. These boards offer the simplest way to build circuits, because you don’t have to solder anything – everything is simply plugged in. Nonetheless, I use these only reluctantly, because circuits built on them have a few disadvantages:

Fig. 4.1: Breadboard connections

You often have to deal with loose wires and contact problems. Wires that are not quite straight anymore or have solder on them are often difficult to connect, and easily get stuck. This makes it difficult to pull them out again and it wears out the contacts. In addition, such a plugged circuit is not as suitable as a permanent solution, but only as a test setup. Finally, you want to reuse your breadboard for other circuits, and any shaking or vibration can easily impair the circuit’s function. Soldered connections are better for permanent builds, in any case. 47

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 44

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

4.2 Point-to-point construction This is how the first TVs and radio tubes were wired in the past. The larger components (in the picture on the right, for example, tube sockets, etc.) were attached, and the remaining components were simply soldered to them. To prevent short circuits, longer, bare wires were covered with plastic, silicone, or heat shrink tubing. This construction method is also suitable for our projects. On the small Pro Mini board, you can put the pin headers on from the top, for example, and then solder the pins to the bottom of the board so that the long pins point up. You can then glue the board onto a small wooden plate with some hot glue, and wire the rest of the circuit onto it. Fig. 4.2a: Point-to-point construction

Fig. 4.2b: Point-to-point construction of transistors and resistors

You have to consider which components are likely to heat up during operation. These are usually transistors, larger resistors, and other power components. Of course, hot glue doesn’t make much sense for them, because it goes soft again under heat. In the example on the left, the heat sink was affixed using heatresistant glue. On capacitors and component leads, however, there’s no significant heating.

The LilyPad is even better suited for point-to-point wiring than the Pro Mini. Its large connection surfaces are perfect for soldering, especially if you’re still inexperienced with a soldering iron.

Fig. 4.2c: Resistors on a LilyPad →

48

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 45

2022-07-27 20:20

Chapter 4 • Optimal construction

4.3 The thumbtack technique An optimized form of point-to-point construction is the use of thumbtacks, which serve as a soldering surface on a plywood board of at least 8 mm thick. We can place thumbtacks on it for all connections, or only sporadically to fix the circuit on place. For a few projects here, there are construction diagrams that we can simply place directly onto the board. The positions of the tacks and components are indicated on them, and the center of the tacks is marked by a small cross, in each case. This way, we can position everything exactly and build the circuit directly on the construction diagram. Ideally, this looks like the picture on the right.

Fig. 4.3: Construction on the diagram

4.4 Perfboards For little cost, you can get all kinds of universal boards with 2.54 mm grid-spacing. They’re available with with single solder holes, strips, or other patterns. In principle, any circuit can be built with them. In practice, however, it is usually a bit tedious to connect or cut the necessary contacts, as and when you need them. Point-to-point construction is easier. Nevertheless, I’d briefly like to cover the most common boards:

Hole matrix These boards have only a single solder joint per hole. The required connections (which would usually be tracks on regular printed circuit boards) must be done using wires of shorter or longer lengths on the underside of the board. Where wires have to cross, it’s best to lay a wire bridge on the top. For more distant connections, we can take an insulated wire, lay it on the top side of the board and solder it through the neighboring holes.

Fig. 4.4a: Hole matrix board

You can, of course, do all of this, but it’s not necessary. In my opinion, the hole matrix board is the most tedious way to build a circuit. 49

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 46

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Stripboard On stripboard, the individual solder holes are all connected together in either a horizontal or a vertical direction, forming continuous strips. This makes it easier to build circuits if the components are arranged cleverly. You basically have all the connections you need at the outset. However, some of the rows may have to be cut in order to make several short strips out Fig. 4.4b: Stripboard of one continuous one. This is best done with a cutter knife, which you use to carefully pry through the copper layer. Repeat this at a distance of half a millimeter, so that a tiny piece of the copper layer crumbles out. This way, the connection is safely severed. If you require additional connections, these are done using wire bridges on the top side. All in all, I think stripboard is more practical than hole matrix boards. However, construction is not really easy.

Other grid arrangements There are all kinds of special grid boards, e.g. strip grids, where groups of only three soldering points are connected in very short strips, or even special arrangements, where an IC is placed in the center and the connection lines are all led to the outside with several holes per connection strip, etc. In principle, these special boards can be very helpful. You only need find the right one for Fig. 4.4c: 3 x 1 grid your purpose, so that as few as possible additional connections or cuts are necessary for the planned circuit. From China, for exam ple, you can also get very cheap mini boards, which are intended especially to accommodate smaller ICs, including for various SMD ICs, which we would not otherwise be able to use at all. (SMD means “Surface-mounted device.” This are very small parts which are soldered directly onto the circuit traces. For example, the ATmega328 and the other parts on the Pro Mini board are SMD components.) 50

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 47

2022-07-27 20:20

Chapter 4 • Optimal construction

4.5 Construction on printed circuit board By this, I mean a proper circuit board designed specifically for the circuit in question. It’s obviously always better so simply insert the components and solder them on the bottom side of the board. It saves a lot of effort if there’s a board designed for the circuit. In “Test and charging station for lithium-ion batteries” in section 8.5 on page 127 , I have created a PCB layout that also works for “Regulated current source” in section 8.6. This board can even be used for the simple constant-current source in section 8.4. For the rest of our circuits, no printed circuit board is necessary. For example, we can solder a multi-digit 7-segment display directly to the Pro Mini, as described on page 237. In other situations, often only a single sensor has to be connected, or the construction is so unique that it would be difficult to do on a uniform circuit board. For this, I recommend point-to-point construction (possibly with a few thumbtacks). In the past, electronics hobbyists often made boards themselves – exposed them through foil, developed them, etched, and drilled them. Today, fortunately, there are companies that offer the service at a reasonable price. For this reason, the downloads for this book contain not only the program sketches, but also the circuit boards in Gerber as well as bitmap formats. The downloads are available for free at elektor.com/20243 The Gerber data consists of several files, each representing a different layer of the board (traces, holes, labeling, etc.). They contain the vector information, and can be opened with a text editor, although there’s not really any point in doing that. On the internet, there are many companies from whom you can get some single boards made from the Gerber files (which should be enclosed in a zip file) – allpcb.com and jlcpcb.com come to mind. It can also be useful to search the title of this book on Ebay, or use search terms such as “arduino charging station board.”

51

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 48

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

4.6 Pin header connectors When I need to connect a multi-pole part (e.g. a motor or sensor), I like to use the type of pin headers that come with the Pro Mini board, as well as their matching socket headers. To both of these (male and female) connectors, you solder the relevant wires, after you’ve added a bit of heat shrink tubing to them. Very important: Plug the male and female connectors together before soldering, as described on page 23 to prevent anything from getting deformed by the heat.

Fig. 4.6a: Male and female headers of various lengths For larger currents (over 100 mA), I use more than one pin (at least 2 per Ampere) to be on the safe side. These are connected to each other, as a single pin might not ensure proper contact, and may heat up excessively. For simple control signals, or for small LEDs driven directly by the Arduino’s output, however, a single pin is always sufficient.

Coded connections For these sorts of pin header connections, there’s a simple way to ensure that the plug cannot be inserted the wrong way around, and that two plugs can’t be mixed up if you Fig. 4.6b: have identical ones of the same length. Your plug and Coded connection socket need to have one extra pin than is required. The extra pin (doesn’t matter which one it is, just not the middle one) is then cut off with a side cutter. Don’t let the pin fly away when you do this, because we still need it. Insert it into the corresponding hole on the female header, exactly where it would normally have plugged in, i.e. the connection that’s now missing on the male side, and leave it there. Now, it’s no longer possible to insert the plug incorrectly, because if you did, the intact pin from the header would hit the pin that’s already occupying the hole. 52

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 49

2022-07-27 20:20

Chapter 5 Programming

Chapter 5 Programming Ordered all the necessary and interesting components? Now, while we wait for our package (from China), we can install the free Arduino-Software on our PC and get familiar with it.

5.1 The Arduino-platform At arduino.cc/en/software, we can download and install the current free Arduino software, or so-called “IDE” (Integrated Development Environment) for various operating systems. At arduino.cc/reference/en, we can access reference detail about all of the elements of the programming language, which is strongly based on C and C++. Once installed, the Arduino IDE looks like this on the PC. In the big white pane, we write our Arduino programs (known as “sketches”). In the black pane at the bottom, information is displayed.

Fig. 5.1: Arduino IDE on the PC

If we click on the circular icon on the top-left with the checkbox in it (✓), the sketch is Verified (checked for errors and compiled). The arrow icon next to it (→) does the same, but also Uploads the sketch to the Arduino if the syntax is error-free. The three remaining icons are for creating a New sketch, and for Opening and Saving, respectively.

We’ll often need to use the magnifying glass icon on the far right, as this opens Serial Monitor – a text window that shows us the data the Arduino is sending when we make use of serial output in our programs. It’s important that the transmission rate selected there matches the transmission rate in our sketch. If not, only garbage (or nothing at all) will be displayed.

53

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 50

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

5.2 Our first program As is customary, our first program will be to blink an LED. This is easy for Arduinos to do, because almost every board already has an LED on it, assigned to an input/output pin. So, for the blinking light, we need only a board, e.g. a Pro Mini, and no further components. First, I’d like to explain the basic structure of an Arduino sketch. These syntax explanations will be identifiable by the light blue boxes in this book.

Syntax: setup() and loop() functions The basic structure of every Arduino program are the setup() and loop() functions. void setup() { […] } void loop() { […] }

// This function is run once, at the start of execution. // The content of this function can consist of many lines. // The loop() function is repeated continuously. // The double-slash causes the rest of the line to be ignored.

The setup() function is executed only once, at the beginning (after switch-on or reset). After that, the loop() function is repeated endlessly. The curly braces are used to group several instructions (denoted here only as […]) into a block. The content of such a block is usually indented, using the Tab key. The Arduino IDE automatically indents code on the next line after you enter an open brace { and press Enter. All of this together makes a function. For beginners it may be irritating that only for the curly brackets separate lines are used, but this serves the clarity, whereas many programmers like to write the opening bracket still at the end of the previous line. By the way, the double slash “//” is used to mark a comment. From there on, the rest of the line is not interpreted as part of the program code.

54

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 51

2022-07-27 20:20

Chapter 5 Programming

Sketch: Our first program

5_2.ino

void setup() // This function is executed only once at the beginning. { pinMode(13, OUTPUT); // pin 13, the LED pin, is set as output } At the beginning here, we set Pin 13 as an output. This is the pin that’s connected to the small LED on the board. (By the way, all of the sketches in this book are divided into individual program sections and explanations, separated by this zigzag line. The explanation always refers to the program section above.) void loop() // This function is repeated endlessly. { digitalWrite(13, HIGH); // LED on delay(100); // wait 100 milliseconds digitalWrite(13, LOW); // LED off delay(100); // wait 100 millisecond } Here, the board’s LED is turned on, and, after 100 milliseconds, is turned off. After another 100 ms, the fun begins all over again. This creates a fast blinking effect. A detailed explanation of the pinMode(), digitalWrite(), and delay() functions will follow later.

If you like, you may enter other time delays into the sketch and try them out. The blinking frequency is easily derived from the two delay times:

Blink frequency = 1 / (0.1 s + 0.1 s) = 5 Hz

5 Hz was chosen here in order to be quite fast, as new boards usually come with a slower blink sketch already installed with the Bootloader. (If the new board doesn’t blink, it may not have a bootloader installed.)

55

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 52

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

5.3 Uploading programs To upload the sketch to our board (e.g. the Pro Mini), we need a serial adapter with a USB connector, which we already know from Chapter 2. Furthermore, we have to specify the correct board in the IDE. There are 4 versions of the Pro Mini (each with either an ATmega168 or an ATmega328 and running at either 8 MHz or 16 MHz).

Fig. 5.3: Selecting the appropriate board version in the IDE Under Menu→Board, select “Arduino Pro or Pro Mini.” Then, below the Board option, we see the “Processor:” menu item, where we must select the correct version. Depending on the USB adapter used, we may also need to use the Port menu option to select the correct port. We should try this if uploading our sketch fails. Incidentally, with LilyPads, we have to be ensure that it really is an 8 MHz-compatible version, as, from China you sometimes get 16 MHz versions much cheaper (even though official 16 MHz LilyPads don’t exist), so you can’t select them in the IDE. For these knock-off LilyPads, we need to select an “Arduino Pro or Pro Mini” board at 16 MHz. Otherwise, delays, timers, and serial connections will end up running at twice the intended speed. 56

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 53

2022-07-27 20:20

Chapter 5 Programming

5.4 Downloading the programs This Blink sketch, as well as all of the upcoming sketches, are available for free download on the Elektor website at elektor.com/20243 which avoids tiresome and errorprone typing. It’s best to extract these programs into the Arduino folder on the PC. In Windows, you’ll find a folder named Arduino in the user’s own documents folder (e.g. C:\Users\UserName\Documents\Arduino or similar). When extracting, the individual folders (with the project names), must be extracted as well, not just the .ino files, because they’ll only run if they’re located in a folder of the same name.

57

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 54

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Chapter 6 • Board inputs and outputs

Fig. 6: Pro Mini inputs and outputs

The ATmega328 (and 168) has 20 pins, each of which we can set as an input or an output. They are numbered from 0 to 19, or alternatively, 0 to 13 and A0 to A5. Designations 14 and A0 are thus equivalent. 6 of these inputs – A0 to A5 (resp. 14 to 19) – can also be read as analog. Two further input pins, A6 and A7, on the other hand, can only be read as analog, but not switch or read digitally.

6.1 Reading inputs digitally In the simplest case, one uses an input to register when a button or switch is pressed. In the example on the right, the voltage at the input is pulled to ground (0 volts) by the resistor. The input itself is very high impedance, and therefore hardly influences the voltage. If the input is read, the result is "LOW” or 0. If the switch or pushbutton is now activated, a HIGH level of (almost) operating voltage VCC is present at the input, which is then read accordingly as “HIGH” or 1.

Fig. 6.1a: Switch to VCC

Usually, the switch is connected to ground and the resistor to the positive pole (VCC), so the signal is inverted. When it’s off, we get a “HIGH” signal, and a “LOW” when it’s on. The 1 kΩ resistor is actually superfluous in both circuits. It only serves as protection in case the input is accidentally set as an output. This could cause a short circuit with the switch and the Arduino would be in serious danger. Nevertheless, this resistor is also often omitted, i.e. replaced by a direct connection. Fig. 6.1b: Switch to GND

58

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 55

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

The digital inputs are always read as “LOW” if their voltage is close to ground (somewhere between 0 and 1 volts). Voltages close to VCC (i.e, at a 5-volt operating voltage, about 4 to 5 volts) are interpreted as “HIGH.” In the mid-range (e.g. at 2 volts), on the other hand, the result is undefined. But, we can omit the resistor to VCC, because the ATmega328 (and of course the 168) already has such a resistor internally at each input. You only have to activate it via software, which can be done for each pin individually. A free (unconnected) input is then no longer hanging undefined in the air, but is pulled up to plus by the internal pull-up resistor. So, for switching, we only need the switch itself (and possibly the much smaller protection resistor). Incidentally, this internal resistor is very imprecise and can be between 20 and 50 kΩ, but this does not have to concern us.

Fig. 6.1.d: Input examples

Fig. 6.1c: Pull-up resistor

Of course, digital inputs can also be controlled by other components, e.g. via a sensor with a digital output. The picture also shows an example with a transistor that can switch the input to ground. Here, too, the internal pull-up resistor can be put to good use. The incoming signal is inverted by the transistor.

To read an input pin with a program and do something with it, we need some new language elements. The second light blue box on the page after the next one describes the actual reading of the pin. If you are already familiar with the programming language, you can safely skip that pages.

59

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 56

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Syntax: Variables In principle, variables are simply storage areas that are allocated by giving them a name. byte a; // A variable of type “byte” is defined byte a = 12; // This is how a variable is both defined and initialized with a value a = 15; // This way a variable is assigned a value, after it has already been defined Variable names can also be much longer and contain upper and lower case letters, as well as the underscore. Even digits can be included in the name, but not as the first character. These are the different variable types: bool Or also “boolean,” a single bit that may only be “0” or “1,” or rather “false” or “true.” You could also say “LOW” or “HIGH.” These terms are all interchangeable. byte A byte is, as the name suggests, a simple byte, consisting of 8 bits. It can hold values from 0 to 255. char In principle, also a byte, but it’s used to hold characters, i.e. those that use ASCII codes. For example, ‘A’ is 65. Instead of 0 to 255, the range for char is -128 to 127 (on the Arduino platform, at least). int Consists of 2 bytes, represents integers between -32,768 and 32,767 unsigned int Like “int,” integers, but the range is from 0 to 65,535 long Integer consisting of 4 bytes, ranges from -2,147,483,648 to 2,147,483,647 unsigned long Like “long,” an integer, but from 0 to 4,294,967,295 float Can be used for numbers with decimal fractional parts, as well as very small or very large numbers, but only to 6 or 7 digits of precision (no matter their distance before or after the decimal point). Variables can be defined right at the outset (before the setup() function). These will always be valid for the entire program. You can also define variables within functions or loops, i.e. within curly braces {}. Then, they are only valid within these and are redefined on each pass. 60

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 57

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

Syntax: pinMode(), digitalRead() and digitalWrite() The ATmega328 (and 168) has 20 pins (0 to 19) that we can switch as digital inputs or outputs. Alternatively, pins 14 to 19 are also called A0 to A5. pinMode(2, INPUT); n = digitalRead(2); This small example sets Pin 2 as an input. Then the present level (“LOW” or “HIGH,” resp. 0 or 1) is read and the result is stored in the variable “n.” A special form of this would be: pinMode(2, INPUT_PULLUP); n = digitalRead(2); Yes, you’ve guessed it: Here, the internal pull-up resistor is also activated. In this way, you’ll always measure a “HIGH” signal when nothing is connected to the pin. pinMode(13, OUTPUT); digitalWrite(13, HIGH); This small example sets Pin 13 (the pin that already has an LED attached to it on the board) first as an output, and then to the “HIGH” level. The LED lights up. Instead of “HIGH,” you could also write “true” or “1” or insert a variable, which then would determine whether the LED lights.

61

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 58

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Syntax: Comparisons and conditions if (n == 7) { n = 0; } else { n++; } This is a typical example of a condition. While the single equal sign is used for assignment, the double "==" is used for comparison. The result of a comparison is always “true” or “false,” i.e. a “bool” value that determines whether the following part is executed or not. Therefore, instead of a comparison, you can also use a single value - e.g. a variable. Everything that is not 0 or “false” is considered to be “true.” Optionally, you can add the “else” construction after it, which is executed if the condition is “false.” In this example, “n” is reset to 0 if “n” was already 7, otherwise it is incremented by 1. This way you can count the variable continuously from 0 to 7. There are several comparison operators that we can use: == != > >= < 10) { n --; } The while loop is basically the same as an if condition, but with the difference that the content in the braces is not only executed once, but again and again, as long as the condition is fulfilled. In this small (meaningless) example, “n” is reduced by 1 over and over again until it’s no longer greater than 10. If “n” was already smaller at the beginning, the content is not executed at all. do { n--; } while (n >10); This is the do-while loop, a variant of the while loop. Here, the content is executed first and then repeated, depending on the condition. The only difference is that the content is always executed at least once and only afterwards the condition is checked. Here, a semicolon comes after the while condition.

Further information about functions and syntax can always be found on the Arduino website at: arduino.cc/reference/en

Pushbutton switch With a simple little program, we can now try out the use of the inputs. The program turns a pushbutton into a switch. A pushbutton remains switched on only as long as you press it, much like a doorbell. Here we can switch on the LED on the board with a pushbutton (or in the simplest case with wire to ground, which is briefly touched to the input pin). If you release the button, the LED remains on. Only if you press the button again (i.e. if the input pin is grounded again), the LED switches off again… and so on.

63

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 60

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Sketch: Pushbutton switch

6_1.ino

byte led_pin = 13; // this pin is switched byte input_pin = 2; // this pin serves as input (with internal pull-up) bool state = LOW; // current switching state of the output Here, first the input and output pins are defined. Of course you can also change these. The “state” variable stores the respective LED switching state. void setup() { pinMode(input_pin, INPUT_PULLUP); // input with pull-up resistor pinMode(led_pin, OUTPUT); // output digitalWrite(led_pin, state); // switch LED (off when state is LOW) } In setup(), the pins are set as an input and an output and the LED is switched off. void loop() { if (!digitalRead(input_pin)) // when button is pressed { state = !state; // other state ("!" means "not" or "opposite") digitalWrite(led_pin, state); // switch output (LED) delay(100); // wait 100 milliseconds while (!digitalRead(input_pin)) // as long as button is pressed { // nothing (wait until button is no longer pressed) } delay(100); // wait 100 milliseconds } } In loop(), we check if the pushbutton is pressed. The “if” evaluation does not have a comparison here, but only an expression that can be true or false, just as with a comparison. If the key is pressed, “digitalRead()” returns false, because we are not switching to positive, but to ground. The “!” in front of it inverts the signal and now returns “true” if the key is pressed. Only then will the content be executed. In this case, “state” (with the help of the exclamation mark "!") is now toggled. True becomes false and vice versa. The while loop then queries the input pin until the button is no longer depressed. The two delays help to debounce the button press.

64

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 61

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

The script can of course be extended with further program parts in the loop. However, this simple version has a disadvantage: As long as the button is pressed, the program hangs within the empty while loop and cannot do anything else. To prevent this, we need an additional status variable for the button instead of the while loop, in which we store whether the button is currently pressed or not. Only if this variable doesn’t match the newly-read signal (and furthermore only when it’s either pressed or released) the device will be switched – on if it is currently off, and off if it is currently on. The changed state (pressing and releasing) must then of course also be saved to the status variable as true or false each time. In the very last sketch on page 324 we have something similar – also with debouncing. The variable that stores the button state is called “pressed” there.

6.2 Reading analog inputs The ATmega328 (and 168) has not only digital inputs from which it can distinguish "HIGH" and "LOW," but on 8 pins (A0 to A7) it also has analog-to-digital converters (ADCs) that can measure the applied voltage with a resolution of 10 bits, corresponding to a range from 0 to 1023.

Reference voltage Each measurement is relative to a reference voltage, which defines the measuring range. While a measured value of 0 basically corresponds to 0 volts (i.e. GND or ground), the reference voltage corresponds to the highest voltage that can be measured, or the highest value plus 1, i.e. 1024, to be precise. The reference voltage thus determines the measurement range.

VCC as reference By default, the operating voltage, VCC, serves as a reference. Since the Pro Mini boards have a high quality voltage regulator, which regulates VCC quite accurately to 5 V (or 3.3 V for the 8 MHz version), you can measure voltages of up to 5 V (or up to 3.3 V) quite accurately. But, the voltage supply at the RAW pin should be at least 1 V higher than VCC, so that the voltage regulator can work properly. The situation is completely different with battery-powered devices. There, the battery voltage is usually used directly as VCC, for example with the LilyPad. Thus, VCC is not very useful as a reference, because the battery voltage is anything but constant. 65

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 62

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Internal reference In addition, there is an internal reference voltage of 1.1 volts, which is very consistent, but unfortunately not very accurate. What seems like a contradiction at first sight, can be explained easily: From board to board, the reference voltage can vary significantly. On one board, for example, it may be 1.03 volts, and on the next, 1.16 volts. Deviations of ±10 percent are possible. The reference voltage on the board, despite its deviation, is, however, very constant, even if e.g. the temperature or the operating voltage, VCC, changes. Thus, a one-time calibration is always necessary here if you want to measure accurately, which you can do as soon as you know the true reference voltage.

External reference The microcontroller also has a connector to which we can apply an external reference voltage. Unfortunately, this connection is only available on the Uno and Nano boards as the “AREF” pin. On the Pro Mini, we don’t have this connector. Usually we have to limit ourselves to 1.1 volt or VCC as reference, but this is quite enough. In this book, we don't use the external reference anyway.

Syntax: analogRead() and analogReference() n = analogRead(A0); In this example, the voltage at A0 is measured and the result is assigned to the variable “n,” which must be at least in “int” or “unsigned int” format, because a 10-bit value is output, which can range from 0 to 1023. A simple byte would overflow at values above 255. We should also note that measured values cannot simply be retrieved directly (like digital values with "digitalRead()"), because calling “analogRead()” first initiates the measurement, and this takes over 100 microseconds each time. The measuring range is from 0V (GND) to operating voltage (VCC) by default. analogReference(INTERNAL); This switches the measurement range to the internal reference voltage of approx. 1.1 V. Thus, small voltages can be measured independently of the operating voltage. Further possible specifications are “DEFAULT” for the standard range (VCC) and “EXTERNAL” for the “AREF” connection. However, the latter is available only on the Uno and Nano boards.

66

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 63

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

6.2.1 Measuring voltages directly In the simplest case, we apply the voltage to be measured directly to one of the analog input pins. However, this must never be higher than VCC. If we accidentally apply 7 volts (or more) to the measurement input, the microcontroller may respond with smoke signals. So, if we can't guarantee that there is never more than VCC at the measuring input, we need at least a protection circuit such as in the picture on the right. Due to the series resistor, nothing would happen if the voltage is higher, because the microcontroller is internally protected so far. In normal measuring mode, the resistor makes no perceptible difference, because the analog inputs of the Arduino, at about 100 MΩ, have a 10,000 times higher resistance.

F. 6.2.1: Protection

Since there is no resistor connected to ground here, the entire measurement input is extremely high impedance. If nothing is connected, the measurement can result in anything from 0 to the maximum value. To prevent this, an additional 1 MΩ resistor can be connected from the measurement input to ground. The input resistance is then (just under) 1 MΩ. The capacitor filters out interference and thus provides a more stable measurement result. The larger the capacitance, the more stable the measurement result. With smaller capacitors, on the other hand, the measurement reacts more quickly to fluctuations at the input. 100 nF is a good value for most applications. But, if you need 1000 or more measurements per second, it is better to reduce it to 10 nF. With a simple program, we can now take measurements and convert the measured values into volts or millivolts. Before that, let’s take a quick look at a few new language elements that are used in the sketch:

Syntax: Defining constants #define measure_pin A0 This assigns constant “measure_pin” the value “A0.” Such lines at the very beginning of the program are not the usual variable syntax, because instead of the "=," there is only a space. Likewise, there’s no semicolon at the end. When compiling the program, the text “measure_pin” is now replaced everywhere by the value after the space. It is also possible (often even recommended) to define constants like variables but with the word “const” prefixed. Example: const byte measure_pin = 14;

67

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 64

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Syntax: Serial transmission Serial.begin(38400); // enable serial transmission This initializes serial transmission via the UART interface. This is the interface that’s also used to transfer the program to the board, basically an RS-232 interface but with a 5 V- (or 3.3 V-) logic level. The number indicates the speed of the upcoming transfers. 38400 is usually a good choice for this. The transfer is then quite fast, but also not so fast that the board, the PC, and common USB adapters can’t keep up. Serial.print("Hello"); This is how text is be transmitted via the interface. In the Arduino IDE you can use the magnifying glass icon in the upper right corner to open Serial Monitor, a window that shows the output from the Arduino board. Serial.print(x, 3); Without the quotation marks, variables (in this case, “x”) can be output as text. The comma and the number after it are optional – the number allows us to specify how many decimal places should be output, which, of course only makes sense for values in floating-point format. The default value is 2. This means that, if you don’t specify it, “float” values are output with two decimal places. Serial.println("Output with line break "); If you use “println(),” a line break is sent out after the output, so that the next output starts on a new line. We can also create line breaks within the text using “\n.”

Syntax: Calculations and assignments The equal sign, “=,” assigns a value to a variable. Example: “a = 3 * b;” triples the value in variable “b,” and stores the result in “a.” The basic operations are +, -, *, and /. To increment a variable by 1, you could type “a = a + 1;” but there are some simplifications: “a++” does the same. “a--” reduces the value by 1; There are also +=, -=, *=, /= … and so on. “a *= 3;” is a simple way to write “a = a * 3;” and so on.

68

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 65

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

Calculation pitfalls For calculations (e.g. "a * b"), the larger data type of the two variables is always used. So if “a” is a byte and “b” is an integer value (int), the calculation is done on an integer and the result is an integer value. But, we get an overflow and therefore a completely incorrect result if the product, “a * b” (or, in case of an addition, the sum) does not fit into an integer type. Likewise, “a * b / c” produces an incorrect result, even if the result becomes very small from the division and can be assigned to an integer type, because the overflow already took place before the division. In most cases, “a * (b / c)” is also not a good solution. This avoids the overflow, but, since we aren’t calculating with floating-point values, everything after the decimal point is discarded when dividing. The overall result becomes very inaccurate. For example, if “b” is smaller than “c,” the result will always be 0, no matter how big “a” is. Better to use “long(a) * b / c.” Now, “a” is interpreted as a long value (with 4 bytes or 32 bits), and there is no overflow anymore, because the multiplication is now also done on a long type. The result can still be stored as an integer type again, as long as “c” is big enough so that the result is small enough to fit into the int type again. Of course, you could also use floating-point variables and calculate everything using the float type. But such calculations are always slower, and, in this example, only recommended if you really need the result to have decimal places.

Syntax: Rounding up and down b = round(a); Here, the decimal variable “a” is rounded to the nearest integer and assigned to “b.” This is the so-called “commercial rounding.” After the decimal point, everything from 5 up is rounded up. Besides “round(),” there are still: b = floor(a); // this is always rounded down b = ceil(a); // this is always rounded up

69

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 66

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Sketch: Measuring voltages up to VCC

6_2_1.ino

#define measure_pin A0 #define vcc 5.00 // operating voltage in volts (calibrate!) unsigned int amount = 10000; // number of measurements (max. 65535) unsigned int counter = 0; // counts measurements unsigned long measurements = 0; // summed measurements float conversion_factor; // conversion factor to volt float voltage; // voltage in volts Here two constants are first defined “measure_pin” is "A0,” and as “vcc” the operating voltage (VCC) must be defined as precisely as possible. Then the required variables are defined, as explained in the comments. void setup() { pinMode(measure_pin, INPUT); // set measuring pin as input Serial.begin(38400); // enable serial transmission conversion_factor = (float(vcc) / 1024); // conversion factor to volt } In setup(), the measuring pin is set as an input, serial transmission (to output the measured value later) is initiated and the conversion factor for calculating the voltage is determined. In principle, the conversion factor says that a measured value of 1024 corresponds to the operating voltage (VCC). The actual maximum value of 1023 is thus very slightly below this. void loop() { counter++; // count measurements += analogRead(measure_pin); // add new measurement if (counter == amount) // if amount is reached { voltage = measurements * conversion_factor / amount; // calculate voltage // output of voltage in mV and V Serial.println(""); // blank line Serial.print("Current voltage: "); Serial.print(round(voltage * 1000)); // voltage in mV (integer rounded) Serial.print(" mV resp. "); Serial.print(voltage, 3); // voltage in volts (with 3 decimal places) Serial.println(" V"); // Reset all for next counting: counter = 0; // 0 measurements measurements = 0; // nothing measured yet 70

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 67

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

}

}

In the loop, the counter is incremented by 1 each time (starting at original 0), an analog measurement is performed and the result is added to variable “measurements.” Only when the counter has reached the number "amount” is the voltage is calculated, output, and the old value is deleted and the counter is reset.

The program now continuously measures the voltage at A0 and calculates the average voltage after every 10,000 measurements and outputs it serially. With Serial Monitor in the Arduino IDE you can view the voltage as an output. Of course, you could also perform only one measurement and calculate and output the voltage using it. The remaining time (until you want another measurement) could be bridged with a delay() function. But the result is more accurate and has a higher resolution if you take many measurements, and, since the program has nothing better to do anyway, we can use the time wisely this way.

Calibration The calibration here is quite simple. We only have to measure operating voltage VCC as accurately as possible using a voltmeter or multimeter, and enter this above in the second line of the program code as a reference. Of course, the modified program must then be uploaded to the board. All this only makes sense if the voltage remains stable permanently. If you use the voltage regulator on the board (with a higher supply voltage at the RAW connector) this would be the case. If the voltage regulator is very accurate, we can also do without the calibration and enter 5.00 (or 3.30) as voltage.

6.2.2 Measuring using internal ref. & voltage divider To measure larger voltages (greater than VCC) we need a voltage divider. The resulting measurement range can be calculated from the two resistors and the reference voltage used: Umax = Uref * ((R1 / 10 kΩ) + 1) "Umax" is the maximum measurable voltage and "U ref" is the internal reference voltage. (Yes, I know that the inner parentheses are of course superfluous, but I like to do it to avoid misunderstandings).

Fig. 6.2.2: Measurement using a voltage divider 71

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 68

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

By the way, later in section 11.2.2 on page 244 there is an extended version with a 4-digit display – a complete voltmeter using only a few components.

Possible ranges Measure range: R1: (E12-series) up to 5 volts

47 kΩ (39k)

up to 6 volts

56 kΩ (47k)

up to 8 volts

82 kΩ (68k)

up to 10 volts

100 kΩ

up to 15 volts

150 kΩ

up to 20 volts

220 kΩ (180k)

up to 30 volts

330 kΩ (270k)

up to 50 volts

560 kΩ (470k)

up to 80 volts

820 kΩ

up to 100 volts

1 MΩ

R1 can now be selected according to the required measuring range. The table shows the required values, whereby the second resistor (to ground) remains unchanged at 10 kΩ. Here, an internal reference voltage of 1 V (instead of 1.1 V) was used for the calculation, because the tolerance range extends from about 1 to 1.2 V. Thus, it is guaranteed in each case that the calculated voltage can actually still be measured. In addition, R1 was rounded up in each case to the nearest value of the common E12 range. For most ranges, the maximum measurable value is actually still somewhat higher than indicated in the table. Where the next lower value may be sufficient for R1, this is also given in parentheses.

The input resistance results from the sum of the two resistors. If you need a particularly high-impedance input that does not load the measured voltage, you can increase the two resistors by a factor of 10 each. If the measurement still has to react quickly to changes, the capacitance should also be reduced to one tenth (i.e. 10 nF). The capacitor should ideally be installed as close as possible to the Arduino input. Here, we can also output the measured voltage using a brief sketch:

Sketch: Measuring using internal ref. & voltage divider #define #define #define #define

6_2_2.ino

measure_pin A0 // measuring pin gnd_resistor 10.00 // resistor to ground (in kiloohms) r1_resistor 150.00 // R1 (in kiloohms) reference 1100 // internal reference in mV (calibrate!)

unsigned int amount = 10000; // amount of measurements (max. 65535) unsigned int counter = 0; // counts measurements unsigned long measurements = 0; // summed single measurements float conversion_factor; // conversion factor to millivolt float voltage; // voltage in millivolts

72

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 69

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

Here, again, the constants are defined first. In addition to the reference voltage, the two voltage divider resistors must also be specified exactly. Then, the required variables are defined. void setup() { pinMode(measure_pin, INPUT); // measuring pin as input Serial.begin(38400); // enable serial transmission analogReference(INTERNAL); // use internal reference for ADC conversion_factor = (float(reference) / 1024); // conversion factor to mV conversion_factor *= 1 + (r1_resistor / gnd_resistor); // with voltage divider } In setup(), the measuring pin is defined as an input, serial transmission is set up (to output the measured value later) and the internal reference voltage is set as the upper limit of the measurement range. The conversion factor is then first calculated as it would be with direct measurement (without the voltage divider). The voltage divider is then taken into account in an additional line. void loop() { counter++; // count measurements += analogRead(measure_pin); // add new measurement if (counter == amount) // if amount is reached { voltage = measurements * conversion_factor / amount; // voltage in mV // serial output in mV and V Serial.println(""); // blank line Serial.print("Current voltage: "); Serial.print(round(voltage)); // voltage in mV (integer rounded) Serial.print(" mV resp. "); Serial.print(voltage / 1000, 3); // voltage in volts (with 3 decimal places) Serial.println(" V");

}

// Reset all for next counting: counter = 0; // 0 measurements measurements = 0; // nothing measured yet

} In the loop, the counter is incremented by 1 each time, an analog measurement is performed, and the result is added to the variable “measurements.” Only when the counter has reached “amount” is the voltage calculated, output, the old value is deleted and the counter is reset.

73

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 70

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Just as with the direct measurement, you can also view the measured voltage in the Arduino IDE’s Serial Monitor. Each displayed value is also averaged out of 10,000 measurements.

Calibration Calibration is a bit more complicated here, because we now have to specify the internal reference voltage in the program sketch instead of the more-easily-measured operating voltage. By default, the approximate value of 1100 mV I specified. For calibration, we have to measure a voltage that we know exactly. Depending on the measuring range, we can use VCC or RAW by tying the measurement input pin to it. Then, we compare the voltage measured with the voltage displayed (using an accurate multimeter) by the serial monitor and we can calibrate: reference = reference_old * actual_voltage / measured_voltage “reference_old” is the previously-entered reference voltage (1100). “actual_voltage” is the voltage we know or measure using an accurate multimeter, and we see the measured voltage in Serial Monitor. Then we just have to enter the new (corrected) value for the reference voltage in the sketch, and of course reload it to the Arduino. The value should be between 1000 and 1200, otherwise something went wrong. Low-tolerance resistors (±1%) are especially important if several different measurements (at several analog inputs) are to be performed using one circuit. Thus, all measurements are accurate if we have determined and specified the internal reference voltage exactly. If, on the other hand, only one voltage is measured, the resistors’ tolerances may be a bit higher. Then, we get a slightly different reference voltage during calibration, but the measurement is still correct as long as the voltage divider was used during calibration.

6.2.3 Measuring directly using the internal reference If we have to measure only very small voltages of up to about 1 volt, we don’t need the voltage divider, but can apply the signal directly to the input. A 100 nF capacitor and a 10 kΩ resistor – as in the picture – can be useful for protection and smoothing. Fig. 6.2.3: Measuring voltages directly 74

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 71

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

Furthermore, we can use a resistor (e.g. 1 MΩ) to ground, which determines the input resistance. Without this (dotted) resistor, the input is extremely high impedance (approx. 100 MΩ). The voltage divider on the right is not part of the actual circuit, but it might later be useful for calibration by providing a suitable voltage. For the program, we use the same sketch as in section 6.2.2 with voltage divider, only now we omit this line: conversion_factor *= 1 + (r1_resistor / gnd_resistor); // Voltage divider This is the line that adds the voltage divider to the conversion factor. Instead of removing the line completely, you can simply comment it out.

Tip: Commenting out lines When programming, you often make quick changes and try out many things. Most of the time it makes sense to know afterwards what you have changed and what it looked like before. Instead of deleting lines that you might need again later, it is better to comment them out: // conversion_factor *=1 + (r1_resistor / gnd_resistor); // Voltage divider The slashes at the front turn the entire line into a comment. This way you can reuse it later if needed. When testing our changes, we can duplicate the original line, comment out the original, and then change the new one. We can also comment out several lines at once, like this: /* These three lines are now just comments! */

Calibration Here, too, we have to apply a calibration voltage that we know exactly. Since the measuring range goes up to 1 volt, a voltage of between 0.5 and 1 volt is recommended. If you don't have a suitable voltage source at hand, you can make a voltage divider from two resistors to create one. Add a 1 kΩ resistor to ground and another of 4.7 kΩ to VCC (5 volts). This gives us a (calculated) voltage of about 0.88 volts, which we can apply to the input and use for calibration. In addition, we use an accurate multimeter to measure the actual voltage. reference = reference_old * actual_voltage / measured_voltage 75

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 72

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Again, “reference_old” is the reference voltage (1100) previously entered and used in the sketch. The actual voltage is the voltage we know or measure using an accurate multimeter, and we see the measured voltage in Serial Monitor. We now get the corrected value for the reference voltage, enter it in the sketch and upload it to the board. The value should be between 1000 and 1200, or something went wrong.

6.2.4 Measuring current To measure current, we need a “Shunt.” This is the name for an extremely low resistance (often much smaller than 1 ohm), which is connected in series in a circuit. It is only used to determine the current based on the (very low) voltage that drops across it, using the simple formula: I = U / R. The internal reference voltage of 1.1 V is very suitable for the measurement, because the measuring resistance (and thus also the voltage drop) will be very low. With a reference voltage of VCC, e.g. 5 volts, no useful measurement of voltages in the millivolt range would be possible. The picture on the right shows such a measuring circuit with a 1 ohm shunt (in the lower part). The upper part shows (symbolically) a load, which may have its own circuit (e.g. running on 12 V), but both have a common ground. Only the load’s positive side is connected directly to its voltage source. The negative pole of the load goes via the shunt (1 Ω) to the common ground. In this way, the current can be measured on the basis of the voltage drop at the shunt. In this case (at 1 Ω), the measuring range goes up to 1 A, because at 1 A, exactly 1 V drops at 1 Ω, and that’s as far as we can measure using the internal reference (1.1 V ±10%). The load can be anything, e.g. a 12 V power LED. For this, here’s another short sketch:

Fig. 6.2.4: Current measurement

Sketch: Measuring current

6_2_4.ino

#define current_pin A0 #define resistor 1.00 // measuring resistor (shunt) #define reference 1100 // internal reference in mV (calibrate!) unsigned int amount = 10000; // amount of measurements (max. 65535) unsigned int counter = 0; // counts measurements unsigned long measurements = 0; // summed single measurements float conversion_factor; // conversion factor to milliampere float current; // current in milliamperes

76

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 73

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

First, the constants are defined. In addition to the reference voltage, the measuring resistor must be specified exactly. Then come the variables. We now have “current” instead of “voltage.” The rest remains the same. void setup() { pinMode(current_pin, INPUT); // measuring pin as input Serial.begin(38400); // enable serial transmission analogReference(INTERNAL); // use internal reference for ADC conversion_factor = (float(reference) / 1024) / resistor; // calculate factor } In setup(), the measuring pin is defined as an input, serial transmission is initiated (to output the measurement later) and the measurement range is set to the internal reference voltage. The conversion factor here is still divided by the measurement resistor. Thus, we calculate the current instead of the voltage. void loop() { counter++; // count measurements += analogRead(current_pin); // add new measurement if (counter == amount) // if amount is reached { current = measurements * conversion_factor / amount; // current in mA // serial output in mA and A Serial.println(""); // blank line Serial.print("Actual current: "); Serial.print(current); // current in milliamperes Serial.print(" mA resp. "); Serial.print(current / 1000, 3); // current in amperes (with 3 decimal places) Serial.println(" A"); // Reset all for next counting: counter = 0; // 0 measurements measurements = 0; // nothing measured yet } } In loop(), as with voltage measurement, the counter is incremented by 1 each time, an analog measurement is performed and the result is added to the variable “measurements.” Only when the counter reaches “amount” is the current calculated, output, the old value is deleted and the counter is reset.

77

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 74

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Here, too, 10,000 measurements are made each time, from which the current is then calculated and transmitted serially. In the Arduino IDE’s Serial Monitor, we can view the measured current. The measurable range with a measuring resistor of 1 Ω is up to 1 A. But, be careful: The resistor must also cope with the power loss. With 1 A at 1 Ω this is exactly 1 W. But, I recommend using a 2 W resistor at 800 mA upward, to be on the safe side. Such a resistor is a little longer and thicker and therefore does not get quite so hot.

Possible ranges (Almost any) other measuring range is possible. The table is a guide: Current

Resistor (shunt)

up to 1 mA

1 kΩ / ¼ watt

up to 2 mA

470 Ω / ¼ watt

up to 5 mA

180 Ω / ¼ watt

up to 10 mA

100 Ω / ¼ watt

up to 20 mA

47 Ω / ¼ watt

up to 50 mA

18 Ω / ¼ watt

up to 100 mA

10 Ω / ¼ watt

up to 200 mA

4.7 Ω / ½ watt

up to 500 mA

1.8 Ω / 1 watt

up to *800mA (1 A)

1 Ω / 1 watt

up to 1 A

1 Ω / 2 watt

up to *1 A (*1.4 A)

0.47 Ω / 1 watt

up to *1.6 A (2 A)

0.47 Ω / 2 watt

up to *2 A (*2.4 A)

0.33 Ω / 2 watt

up to *2.5 A (*3 A)

0.22 Ω / 2 watt

up to *3.1 A (*3.6 A)

0.15 Ω / 2 watt

up to *3.8 A (*4.4 A)

0.1 Ω / 2 watt

In this way, we can set up measuring ranges with a maximum current of 1 mA up to about 4 A, whereby the power loss in the resistor increases with increasing current. At the lower values in the table, which are marked with asterisk *, the full measuring range up to a 1 V voltage drop is no longer used, but only a part thereof. This limits the power dissipation, so that a 2-watt resistor is sufficient. A disadvantage is the somewhat lower resolution of the measurement results. The 10-bit value of the analog-to-digital converter normally ranges from 0 to 1023, and for the final value, for example, we only use about 40 percent of the range, i.e. from 0 to 400. With the current values in parentheses, the maximum permissible power dissipation of the respective resistor is almost reached. It’s better if we don’t go completely to the power limit and rather limit ourselves to the values before the parentheses.

As with the voltage measurement, all resistors were calculated so that the specified maximum current can be measured in any case. There is never more than 1 volt at the resistor, because the reference voltage at a ±10% tolerance is between 1.0 and 1.2 V. 78

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 75

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

Calibration There are ways we can calibrate here. On the one hand, we can measure the current directly with an accurate multimeter, compare it with the displayed value and calibrate it. On the other hand, we can also determine the exact voltage drop at the measurement resistor, in the millivolt range, using a good multimeter, and calculate the current from this. This may give us a more accurate value for the reference voltage. (This is important if other measurements are also made.) If, on the other hand, we measure the current, deviations in the measurement resistor are also taken into account. Then the current measurement may be more accurate. reference = reference_old * actual_current / measured_current In this way, we determine the internal reference voltage from a current measurement from the load. The current-measuring device is connected in series with the load. The actual current is that which the measuring device (multimeter) displays. “measured_current” means the current displayed by Serial Monitor, not to be confused with the actual current from the multimeter. reference = reference_old * actual_voltage / R / measured_current In this way, we determine the internal reference voltage by means of the voltage drop at the measurement resistor (R). The “actual_voltage” is the voltage measured with the multimeter. The “measured_current” is the one displayed by Serial Monitor. We enter the newly determined reference value (millivolts, rounded as an integer) into the program and re-upload the sketch to the board. The value must be between 1000 and 1200. Otherwise, there’s an error somewhere.

79

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 76

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

6.2.5 Resistor measurement Resistors are best measured with a voltage divider consisting of a known resistor (R1 in the picture) and the resistor under measurement (R?). The positions of the two resistors may also be interchanged, although this changes the calculation formula. The previous disadvantage of VCC as a measurement reference now turns out to be an advantage, because, if VCC is not stable, both the reference voltage and voltage measured change. For this measurement we are no longer concerned with the measured voltage as an absolute value, but only with the percentage of VCC, which is independent of total VCC, and solely dependent on the ratio of the resistors.

Fig. 6.2.5a: Measuring resistance

Incidentally, the measurement is most accurate when the two resistors are approximately the same size. If, for example, if a resistance is to be measured that can lie in the range of 1 to 10 kΩ, then 3.3 kΩ would be an ideal value for R1. This way, the resistors are never more than a factor of 3.3 apart. Many simple sensors are also often implemented by using resistance measurement. The picture on the right shows two common examples – brightness measurement using a lightdependent resistor (LDR) and temperature measurement using a thermistor (NTC). Here too, the most accurate result is obtained if the two resistances are of similar size. If you want to measure the room temperature at home, for example, and the NTC used has a resistance of 47 kΩ at 25 °C, then the same value is recommended for the fixed resistor.

Fig. 6.2.5b: Brightness and temperature measurement

A relatively high-impedance NTC has the advantage that no significant current flows, so it won’t heat up itself during operation and falsify the result. An additional 100 nF capacitor from the analog input to ground can also minimize interference here and thus smooth the measured value.

80

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 77

2022-07-27 20:20

Chapter 6 • Board inputs and outputs

Sketch: Resistance measurement

6_2_5.ino

#define measure_pin A0 unsigned int amount = 10000; // amount of measurements (max. 65535) unsigned int counter = 0; // counts measurements unsigned long sum = 0; // summed single measurements float r1 = 10000; // resistance R1 (example 10 kiloohms) float ratio; // resistor ratio float rm; // measured resistor void setup() { pinMode(measure_pin, INPUT); // measuring pin as input Serial.begin(38400); // enable serial transmission } void loop() { counter++; // count sum += analogRead(measure_pin); // add new measurement if (counter == amount) // if amount is reached { ratio = sum / float((1024 * (long)amount) - sum); // resistor ratio rm = r1 * ratio; // calculate resistance value from ratio

}

Serial.println(""); // blank line Serial.print("Resistor: "); // output follows in ohms, kiloohms or megaohms if (rm >= 1000000) // if at least 1 megaohm { Serial.print(rm / 1000000); // display in megaohms Serial.println(" MΩ"); } else if (rm >= 1000) // if at least 1 kiloohm { Serial.print(rm / 1000); // display in kiloohms Serial.println(" kΩ"); } else // if under 1 kiloohm { Serial.print(rm); // display in ohms Serial.println(" Ω"); } counter = 0; // reset counter sum = 0; // reset sum

} The sketch is largely self-explanatory. The measured value is also averaged out 10,000 times here and then processed further. The variable “ratio” indicates the ratio of the resistors (rm/r1). The output distinguishes 3 ranges (MΩ, kΩ and Ω). 81

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 78

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Swapping resistors If (for whatever reason) the resistors are to be reversed, so that the measured resistor is connected to the positive pole (instead of to ground, where R1 is then connected), the variable “ratio” no longer returns rm/r1 but r1/rm. You then have to divide “r1” by “ratio” in the sketch’s following line instead of multiplying – so replace the old multiplication line with this one: rm = r1 / ratio; // calculate resistance value from ratio

Calibration Calibration is not necessary here if we use an accurate R1 with 1% tolerance, because R1 is the only reference that influences the result. In case of an inaccurate R1 we can also measure using a good multimeter and then enter the correct value in the sketch. Of course, this only makes sense if the multimeter is more accurate than the original specification. So if we use a resistor with 1% tolerance, and our multimeter has 2% tolerance, then doing so makes no sense.

6.3 Switching outputs digitally Similar to reading levels “HIGH” or “LOW” digitally at the input/output pins, we can also switch each pin as an output and send out a corresponding signal. We have already done this on pages 55 and 64 by switching the on-board LED at digital Pin 13 on and off using “digitalWrite().” The exact syntax is explained on page 61. “HIGH” corresponds (almost) with operating voltage VCC. Depending on the load at the terminal – if a current flows to ground – the voltage is slightly lower, for example 4.8 volts at a 5-volt operating voltage. If we switch to the “LOW” level, the voltage changes to (almost) 0 V, and the reverse is now true: Depending on what is connected to the pin – whether a current flows toward the positive pole – the voltage is just above 0 volts. What you can do with the output signal of such a pin, i.e. how to switch something with it, is what the next big chapter is about:

82

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 79

2022-07-27 20:20

Chapter 7 • How do you switch something?

Chapter 7 • How do you switch something? If we want to switch more than just the mini LED on the Arduino board, we need to know what voltages and currents we’re dealing with. Some can be switched directly, while some need a resistor in series. For higher voltages and currents, more resistance is needed. The output lines of an Arduino board supply the operating voltage of the microcontroller (i.e. usually 5 V or 3.3 V, or slightly less) in the HIGH state, and in 0 V in the LOW state (or slightly more). The connections should not be loaded with more than 25 mA each. The absolute maximum allowed is 40 mA, but it is better to stay well below that, especially if we make use of multiple outputs under load. If many outputs are used, the load on each line should be even lower. Depending on the loads’ distribution, we should not exceed a total load of 100 or 200 mA. If we are slightly above this, the microcontroller will not break down immediately, but we don't have to torture it unnecessarily.

7.1 LEDs Simple colored LEDs (red, yellow, green, blue, and white) e.g. in the conventional design of 5 mm or the smaller 3 mm diameter can be operated without any issue on an Arduino output. However, LEDs don’t tolerate 5 V directly. An LED’s current-voltage curve is not linear. The figure shows the characteristic curves of common LEDs and that of a 100 Ω resistor (gray line) in comparison. As we can see, at a low voltage (e.g. 1 V), almost no current flows through the LEDs (in contrast to the linear resistor). At 4 or 5 V, however, a huge current would flow and destroy the LEDs as well as the Arduino. The solution is a simple resistor, which we connect in series with the LED. Such a resistor, with the purpose of limiting the current to be able to operate a component using a higher voltage, is called a series resistor. Fig. 7.1: LED characteristic curve

U(V) 83

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 80

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

7.1.1 Calculating the series resistance

Fig. 7.1.1: LEDs with series resistors R

=

U/I

=

The calculation of series resistance is quite simple. We only need to know three values, the voltage that is applied in total (to the LED and the series resistor), usually 5 volts, the voltage that should be applied to the load (i.e. the LED), and the corresponding current that flows through the LED at the desired voltage. The voltage at the resistor is the difference, i.e. total voltage minus LED voltage. The current in the LED and the resistor is the same. Thus we know the current and voltage in the resistor and can now calculate it:

(Utotal – ULED) / ILED

=

(5 V – 2 V) / 0.013 A

=

230.8 Ω

Here we have used a target current of 13 mA for the LED and an LED voltage of 2 V, which fits relatively well for red, yellow, and green LEDs. Thus we have an ideal value of 230 Ω. The next most suitable resistor (from the E12 series) is 220 Ω here. With blue LEDs it looks a bit different. There, we have to do the math using about a 3 V voltage drop at the LED, so we come to about 150 Ω. R

=

(5 V – 3 V) / 0.013 A

=

153.8 Ω

Often it becomes apparent during operation that the calculated resistance values are not quite optimal, e.g. if the LEDs are too bright or not bright enough in daylight. Sometimes you use several LEDs in different colors and then notice that one color looks brighter or weaker than the others. Then you can correct the values. The lower the ohmage, the brighter the LED. We shouldn’t go below a hundred ohms, as the current becomes too high.

7.1.2 LEDs in battery operation For applications in battery mode with lithium-ion battery we have an operating voltage of about 3 to 4.2 V instead of the 5 V. Here, we can use a series resistor of 150 or 100 Ω for red, yellow, and green LEDs. But we can also save power and stay at 220 Ω (as with the 5-volt operation).

84

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 81

2022-07-27 20:20

Chapter 7 • How do you switch something?

Blue LEDs are difficult to run on batteries, because the voltage difference goes to zero when the battery is almost empty. Thus, the series resistor would also have to go to zero (i.e. conduct fully) to maintain the brightness. With a full battery, on the other hand, the series resistance is definitely required. Therefore, I recommend not using blue LEDs in battery-powered devices. If you want to use them anyway, it’s best to use 100 Ω, but then you have to expect that blue LEDs will weaken a bit when the battery is almost flat. This has its advantage: it can be quite practical, as you can recognize early on that the battery needs to be charged soon.

7.1.3 Switching direction to ground or positive The picture on the right shows another way to switch LEDs and other small loads with an Arduino board. Here, the LED is not (as before) tied to ground, but rather to positive. So, the output now works the other way round: When you switch it to HIGH (VCC), the LED is off. Both sides of the LED are thus connected to the same voltage potential. If you switch it to LOW (or 0), the LED lights up. Fig. 7.1.3a: LED to VCC →

Now you could of course combine the two types of switching, as in the picture on the left. This way, you could make an alternating flasher using two LEDs on only one output. Depending on the switching state, one or the other LED is always lit.

← Fig. 7.1.3.b: Using 2 LEDs

Usually you would create an alternating flasher with two outputs (one per LED), as in Fig. 7.1.1. Then you could also switch both LEDs on (or off) at the same time. This would not be possible here. You could set the pin as an input (and thus deactivate it), but then (depending on the operating voltage) both LEDs would light up weakly or not at all.

85

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 82

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

7.1.4 Project: LED effect board After so much theory we now come to the first practical Arduino project. The LED effect board is a simple setup with up to 20 LEDs arranged in a circle. But you can also start smaller by equipping only every second or every fourth LED, or only an arc of the circle. We can then control the LEDs as we like – an ideal playground for programming practice. There are also a few ready-made effect programs.

Fig. 7.1.4a: Construction using thumbtacks

For the first assembly suggestion, I have created a construction plan with which you can easily build the circuit using some thumbtacks on a small board of soft wood. The thickness should be at least 8 mm, so that the thumbtacks don’t poke through the bottom. You can download the schematic from the Elektor website at elektor.com/20243. If necessary, you can also scan the plan for the LilyPad from page 88 of the book and print it out. On page 89 there is also the Pro Mini version. In any case, the print settings are important, because the printout must be exactly in the original size.

We then place the printed plan on the board and press in the thumbtacks. The Arduino (Pro Mini or LilyPad, depending on the version), goes in the middle, possibly over some hot glue. Then the resistors are soldered on first, then the LEDs, and finally the wire connections. We need: • 1 LilyPad or Pro Mini Board • 5 to 20 LEDs (see text) • 5 to 20 resistors (see text) Depending on construction: • 1 wooden board Ø13.5 cm, 1 cm thick • 1 printed construction diagram • 10 to 40 thumbtacks (2 per LED) Fig. 7.1.4b: Required parts

86

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 83

2022-07-27 20:20

Chapter 7 • How do you switch something?

For the setup in the picture on the right, we use 1-watt LEDs. These are actually completely oversized here, because we only run them at about 30 mW, but they don’t cost much more than standard LEDs and have the perfectly fit for connectors. Of course, you can also use normal 5 mm LEDs (as in the components picture on the previous page). The component leads are then bent outward at right angles (all at the same distance from the LED body) and then cut to fit the solder pads.

Fig. 7.1.4c: Circuit ready soldered

Fig. 7.1.4d: Circuit diagram

Determining resistor vales The required series resistors depend mainly on two factors – firstly, the operating voltage used, and secondly, whether blue or white LEDs (as opposed to red, yellow, and green) are used, as the blue and white have a slightly higher operating voltage. The 8 MHz board can be operated on 3 to 5.5 V (3 V to 4.2 V in battery operation). The 16 MHz version, on the other hand, operates with a fixed 5 V. The optimal series resistors, depending on LED color and operating voltage, are shown in this table: Red, yellow, or green LEDs

White or blue LEDs

3 to 4.2 V operating voltage

220 Ω

120 Ω

5 V operating voltage

330 Ω

220 Ω 87

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 84

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

For white or blue LEDs, the operating voltage should be at least 3.5 V. Of course, you can also use 330 Ω in general, and then you’d be on the safe side in any case, even if the LEDs end up being not be quite as bright.

LilyPad construction template

Fig. 7.1.4e: LilyPad construction template This version is easy to build, and especially suitable for battery operation. However, we have to bend the 6-pin header (with the connected female header) away a little, so that the USB adapter can still be plugged in. At the same time, we have to press the header against the board, so that the solder connections don’t break off during bending. 88

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 85

2022-07-27 20:20

Chapter 7 • How do you switch something?

Pro Mini construction template

Fig. 7.1.4f: Pro Mini construction template This version is not as easy to solder because of the smaller contacts, but it can be operated at a higher voltage (up to 9 volts) at the RAW input.

89

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 86

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Before I present the effect programs for the LED board, I need to explain a few programming basics. If you’re already familiar with these, you can skip this section.

Syntax: Arrays Sometimes you need a whole array of similar variables that are sequentially numbered. When creating such arrays, you simply put the required number in such brackets after the variable name: bool led[20]; This creates an array of 20 boolean variables, from led[0] to led[19]. When programming, you always start counting with 0, so it’s not 1 to 20 but rather 0 to 19. When addressing variables later, their indices can also be variables themselves. Example: led[n]. Thus, the variable “n” indicates which indexed member of the led[] array is needed. byte pin[20] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1}; If you want to initialize the array with values for the individual indices, you can do so in this way. The individual values are enclosed in braces, separated by commas.

Syntax: for loop for loops are usually used when you want to repeat statements several times. A variable (in the following example, “n”) serves as a counter. for (byte n = 0; n < 20; n++) { led[n] = HIGH; } Here a variable, “n,” is defined and set to 0. (If the variable already exists, leave out the data type keyword, “byte”). Then the condition “n < 20” is checked. At first, this will be the case, therefore the program block between the braces {} will be executed: led[0] is set to HIGH. After that, “n++” is executed, so “n” is incremented by 1. Then, the condition “n < 20” is checked again, and so on. At some point, n will reach 19. led[19] is set to HIGH and “n” is increased again. At this point, “n” is equal to 20, and the condition is no longer fulfilled. The loop is exited. That makes 20 passes, with “n” going from 0 to 19.

90

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 87

2022-07-27 20:20

Chapter 7 • How do you switch something?

Syntax: delay() and system time delay(1000); This simple instruction creates a delay of one second, because the specification is in milliseconds. With the largest possible number (4,294,967,295 for unsigned long) the Arduino would wait for almost 50 days. delayMicroseconds(100); This creates very short delays, because here the specification is not in milliseconds but in microseconds. Here, only values up to 16,383 should be used. In addition, the Arduino also has two system times that start at zero after power-up (or reset): millis() returns the elapsed time in milliseconds, in unsigned long format. micros() returns the elapsed time in microseconds in unsigned long format. But the actual resolution is 4 times lower, so the value changes only 250 times per millisecond in steps of 4 for the 16 MHz version, or steps of 8 on the 8 MHz version.

91

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 88

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Simple LED effect This program changes the state of the LEDs (on/off) continuously one after the other. First, all LEDs go on one after the other, then off one after the other… and so on. If the effect runs very fast, it looks like a continuous rotation movement, similar to some waiting icons seen on a PC screen. Let's look at the sketch:

Sketch: LED rotation effect

7_1_4_a.ino

// Settings: byte amount = 20; // total number of channels resp. LEDs (3 to 20) bool active = LOW; // outputs high- or low-active byte pin[20] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,0,1}; // pin order int blink_time = 50; // time in milliseconds each time until the next change In this first part of the program, we first define the basic settings using 4 variables. In the variable “amount” we first have to specify how many LEDs are be used in total. “active” specifies whether the LEDs are lit up, using LOW or HIGH. Since we connected the LEDs to VCC, not ground, LOW means switched on. pin[20] is an array, where we have to specify the pins used, in order. For example, if we only populated every fourth LED, then, starting with Pin 2, we’d have “{2, 6, 10, 14, 18}”. By the way, it is recommended to always start at Pin 2, so that Pins 0 and 1 are the last two, because these are used for serial transmission (TX and RX) and should therefore only be used for the LEDs if you really need them. bool led[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // current states of LEDs byte n; // count variable Two more variables are defined here. led[20] is also an array that indicates the current switching state of each individual LED. This is initially filled with zeros, since all LEDs should be off at the beginning. The variable “n” is used for counting and later indicates which LED we’re currently working with.

92

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 89

2022-07-27 20:20

Chapter 7 • How do you switch something?

void setup() { for (n=0; n= amount) // if total number of LEDs is reached { n = 0; // reset counter } led[n] = !led[n]; // toggle state entry (switch on/off) digitalWrite(pin[n], led[n] == active); // switch output accordingly delay(blink_time); // wait (as defined) } In the loop, “n” is increased by 1 with each pass. However, when the LED count (20) is reached, “n” is reset to 0. This way, we only count from 0 to 19. Then the indexed LED with the respective number is toggled in the array: led[n] = !led[n]; The exclamation mark means “not,” which means that “true” becomes “false” and vice versa. Then, the new (toggled) value is sent to the pin using digitalWrite() (as was done in setup()). The last step is to wait using delay(), for as long as is specified in blink_time. The specification is in milliseconds, so 1000 would be one second.

The complete sketch is also available for download (as are all the others) on the Elektor website at elektor.com/20243

93

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 90

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Your own versions If you like, you can also play around by changing the settings at the beginning, tinker with the program code, or even create your own programs. Example: n = random(amount); If we replace the first half of the loop function (where "n" is specified) with this line, then a random value from 0 to amount-1 is generated on each pass. This way the LEDs will be switched completely randomly.

Syntax: Random values with random() With random(min, max) you can easily generate integer random numbers from “min,” inclusive up to “max,” exclusive. n = random(1, 21); Here, the variable “n” is assigned a random value between 1 and 20. The first number can also be omitted if it is 0: with random(0, 20) or simply random(20), we get random numbers between 0 and 19. Strictly speaking, random numbers are only seemingly random. In reality, it is a fixed series of over 4 billion numbers generated by an algorithm. To avoid getting the same sequence of numbers every time you turn the board on, you can use randomSeed(): randomSeed(analogRead(A7)); This defines the position (in the algorithm) for the next random number. If you use the analog value of an unused input (as in this case), it will be something between 0 and 1023, which is relatively random.

Here’s another program for the LED board:

LED running light effects With this program we can define an arbitrary LED light pattern in advance, and let this pattern run in a circle with at an arbitrary speed. This sounds similar to the previous program, but is quite different. While previously only the position where the LEDs are currently switched rotated, here the entire light pattern rotates.

94

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 91

2022-07-27 20:20

Chapter 7 • How do you switch something?

Sketch: LED running light effects

7_1_4_b.ino

// Settings: byte amount = 20; // total number of channels resp. LEDs (3 to 20) bool active = LOW; // outputs high- or low-active byte pin[20] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,0,1}; // pin order bool led[20] = {1,0,0,0,0,1,1,1,0,0,0,0,1,1,0,0,0,0,1,1}; // blink pattern char movement = 1; // number of positions, the pattern moves at each pass int blink_time = 200; // time in milliseconds each time until the next change Here again we have the same variables for the basic settings. What’s new is the blinking pattern, which we can specify in the led[] array using 1s and 0s. The “movement” variable specifies how this blinking pattern moves. Here, we could use -1 to change the running direction, for example. byte led_new[20]; // new blink pattern byte n; // count variable char pos; // LED position There are further variables here that the program needs. led_new[] is (like the led[] array) an additional array for the LEDs’ switching states, which is later used temporarily when moving them. “n” is again for counting, and “pos” is the respective shifted position of “n.” void setup() { for (n=0; n= 3) // if overflow (i.e. greater than 2) { color = 0; // start again with color 0 } } Now, the next color is processed, and, if necessary, reset, so that the next color is processed on the next loop pass.

Usage When the program starts, all three LEDs are turned off immediately, and then they begin changing their respective brightnesses at different speeds. The mix of all three of them produces pretty colors, which you can recognize as as mixed colors only if you don’t look directly at the single LEDs, but at the combined light of all LEDs, e.g. if you illuminate something with them.

Tip: Small test with LED effect board If you built the LED effect board (with LEDs on Pins 9, 10, and 11), you can also test the Flowing color changes sketch. This way, you can see the different quick brightness processions, even if without colorful RGB colors.

113

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 110

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

8.2 Low-pass demodulation It is also possible to generate a real DC voltage from a pulse-width modulated signal. In the simplest case, all we need is a resistor and a capacitor, which we connect together to form a low-pass filter, as shown in the picture on the right. What happens with our PWM signal here?

Fig. 8.2a: RC low-pass

Fig. 8.2b: Low-pass filtering a PWM signal with a 75% duty cycle The graphic starts on the left, showing a switched off signal (duty cycle 0%). The output voltage at the capacitor (that’s the red line) is also 0. Then, a PWM signal with a duty cycle of 75% is sent to the Arduino output, and, as the red line impressively shows, the capacitor is already charging very slowly from the first pulse, always in a way that corresponds to the current switching state. With each active pulse, the voltage increases a little, and in each gap between pulses, it decreases again slightly. Eventually, the voltage settles at a level that corresponds to the duty cycle. In our example with a 5-volt pulse voltage and a duty cycle of 75%, this would end up at about 3.75 V. We can also see from the red line that the DC voltage is not perfectly smooth. A small residual ripple remains. We can reduce this with a larger capacitor or resistor, but, let’s see what happens then:

Fig. 8.2c: Low-pass filtering with a larger capacitor on the PWM signal Here the capacitance was doubled. The residual ripple has thus halved. On the other hand, it now takes twice as long for the signal to settle at the 75% level. So, choice of components for the RC circuit is always a compromise between ripple and signal sluggishness.

Time constant

τ

As a guide, the time constant τ (Greek: “tau”) can assist. τ denotes the time it would take to reach the final value (75%) if the capacitor voltage maintained its initial rise. 114

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 111

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

This corresponds to the green line here. After 6 pulses, where the green line ends, it has reached the final value of 75%. After one pulse, at the small vertical green mark, the capacitor voltage (red) is still nearly as high as the green line, but the slope is decreasing. Fig. 8.2d: Initial rise seen in green (If you look closely, you can see that during the first pulse, the red line is even steeper than the green line, but, as long as the pulse is active, the capacitor voltage is heading toward 100%. If we extended this slope as a line, we’d get to 100% after the 6th time period). In fact, the capacitor voltage has adjusted to the final value after a time unit τ of a good 63%. This can also be seen in Figure 8.2d by the small vertical red mark, which corresponds, in this example, to the time unit after 6 clock cycles. The red curve has already approached the target value here to a good 63%. After two time intervals, it would be 86.5%, and after 3, 95%. After 5 time intervals one assumes a (nearly) complete adaptation at over 99%. The voltage at the capacitor has then completely reached the target value of 75%.

Calculation

τ is very simple to calculate:

τ

= R  C

In our example (4.7 kΩ and 100 µF) this means:

τ = 4.7 kΩ  100 µF = 470 ms

After just under half a second, the voltage at the output reaches a good 63% of the target value. After 2 seconds, it’s already about 99%.

Ripple The ripple can also be calculated approximately:

ΔU = Ub / (4  f  R  C)

The triangle (Greek: “delta”) stands for the difference, in this case for the ripple. Ub is the operating voltage (which we simply equate with the pulse voltage here), f is the PWM frequency, and R and C represent the components used. So, let’s do the math: ΔU = 5 V / (4  490 Hz  4700 Ω  0.0001 F) = 0.0054277 V = 5.4277 mV A little more than 5 millivolts, which is very little and thus an excellent result. If we reduce the capacitance by a factor of 10, to 10 µF, or the resistance to 470 ohms, the ripple increases to 54 mV, which is still quite acceptable. Any change in the PWM value would then be reflected achieved after just a fraction of a second. 115

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 112

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Two-stage filter Another option is to use two RC filters in series, as in this example. Then you can choose much smaller capacitances (or resistances). While there is still a slightly higher ripple after the first electrolytic capacitor, you get a very clean DC voltage after the second one. An exact calculation is difficult because of their mutual influence on each other. Fig. 8.2e: Two low-pass filters

8.3 Regulation with a feedback loop We can control voltages even more precisely by adding feedback control. To do this, we simply apply the output signal to one of the analog input pins. During program execution we can measure the actual voltage repeatedly and correct the PWM signal accordingly. In this way, voltages can be set even more precisely and changes may also be achieved more quickly.

Fig. 8.3: PWM with feedback

8.4 Project: Adjustable constant current source This circuit provides a precisely adjustable constant current. It is very well suited to supply power LEDs, for example, with constant current, or also to charge rechargeable batteries. For lithium-ion batteries, however, the next circuit (8.5) should be used.

We need: • • • • • •

Pro Mini Board (ATmega168 or 328) T1 BD435 (possibly with heat sink) R1 100 Ω / ¼ W R2, R3 22 Ω / ¼ W R4 1 Ω / 1 W (see text: “adjustment”) C1, C2 1000 µF / 10 V

There is no construction plan here, but you can use the next circuit’s (8.5) construction plan for this version, too, and build the circuit with a PCB or freely wired with a few thumbtacks on a small board. The component numbers are identical to those in this version.

116

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 113

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

The picture on the left shows the use of the circuit board of circuit 8.5. All gray components are not used here yet. The load is connected to B-. At B+, the board is supplied via the RAW connector. This pin is also the positive pole for the load, if its voltage supply is not above 12 volts. The technical explanations of these circuits, 8.4 to 8.6, can be quite detailed and are not always easy to understand. But, you don't have to understand their full functionality to rebuild and use them. From Chapter 9 onward, it gets easier again.

Fig. 8.4a: Built with 8.5 PCB The RC filters at the PWM signal are of much lower impedance than in the previous examples, because some current is needed here to drive the transistor. The amplified current at the emitter also flows through R4, causing a corresponding voltage drop across it. This voltage in turn raises the emitter potential of the transistor. This again counteracts the base-emitter voltage and the current.

Fig. 8.4b: Adjustable current source using PWM

In relation to R4, transistor T1 thus works as a common-collector circuit, also known as an emitter-follower. The voltage at R4 always accords with the base voltage, but always distanced from the base-emitter voltage, which remains relatively constant at approx. 0.7 V (or perhaps a bit more, depending on the current). T1’s base voltage results from the board voltage and the duty cycle, minus the voltage drops at R1, R2, and R3 due to the base current. The base current, in turn, depends on the transistor’s amplification factor, which we don’t know exactly. In short: An exact pre-calculation of what current flows from which PWM signal is not possible here. But, we solve the problem by feeding back the emitter voltage to an analog input. Current and voltage in R4 are proportional to each other (U = I  R). So, if we know what current is to flow, we also know the voltage that must be present at R4. We can now measure this exactly and correct the PWM signal repeatedly until we get exactly the right voltage at R4 – and thus the desired current. 117

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 114

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

The prerequisite for all this is, of course, that the corresponding current can flow at the collector of the transistor. For this, a load with a voltage source must be connected, which then also draws current. Without a load, the program would set the duty cycle to maximum (100%) and still no current would flow (apart from the much lower base current).

Customization Depending on the required output current (or current range), we can also adapt the circuit. With an R4 of 1 Ω / 1 W, we can control a maximum of 1 A, because 1 V drops and 1 W is used by the resistor. But I recommend not loading the resistor completely to its limits, and rather using a 2 W resistor for currents above 800 mA. For even higher currents, we have to reduce the resistor value to 0.47 Ω, because a maximum of 1 volt is permitted to drop off. We cannot measure more than that (with the internal reference voltage of 1.1 V ±10%). The table shows the range of measurements achievable for each value of R4. Also borne in mind is the fact that we don’t want to operate the resistors right at their limits. The values in parentheses, on the other hand, show the full load capacity of the respective resistors. (For 1 Ω / 2 W this value is missing, because the drop would be over 1 V).

Current (max)

Shunt R4

up to 800 mA (1 A)

1Ω/1W

up to 1 A

1Ω/2W

up to 1.2 A (1.4A)

0.47 Ω / 1 W

up to 1.7 A (2A)

0.47 Ω / 2 W

up to 2 A (2.4A)

0.33 Ω / 2 W

The exact resistor value used must be entered into the sketch above as a defined constant so that the current is correct. You can also use a 0.47 Ω resistor for smaller currents, if you want to keep the voltage drop at R4 small, but the resolution of measurement will be reduced somewhat. If the transistor has to handle more than 1 W, we need a cooling plate or a small heat sink. The power dissipation results from the transistor’s collector-emitter voltage (essentially the difference between the operating voltage and the voltage applied to the load), multiplied by the maximum current flow. Example: At an operating voltage of 15 V, of which 10 volts drop out at the load (i.e. max. 5 V at the transistor), a current of max. 200 mA may flow without a heat sink, because 200 mA  5 V equals 1 W. Before we get to the sketch containing the current-control source code, on the next page is an overview of the new language elements used in it:

118

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 115

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

Syntax: Bitwise operators a = 21 & 7; The & sign is the bitwise AND operation – used to compare numbers bit-by-bit. In the result, only the corresponding bits that are 1 in both numbers are set to 1. For our example, this means, bit-by-bit: a = 00010101 & 00000111 = 00000101, which is 5 in decimal. a = 21 | 7; Like AND, but OR instead. In the result, every corresponding bit is 1 if it was 1 in at least one of the compared numbers. For the example: a = 00010101 | 00000111 = 00010111, which is 23 in decimal. a = 21 ^ 7; In the XOR (exclusive or) operation, a result bit is 1 if exactly one of the corresponding bits in the inputs was 1, i.e. if the bits in each number is different. For our example this means: a = 00010101 ^ 00000111 = 00010010, which is 18 in decimal. a = ~21; The NOT operator is only applied to a single number and is used as a prefix. It simply causes an inversion of all bits. In our example, the binary would be: a = ~00010101 = 11101010, which is 234, provided it is a single byte. (All of these bitwise operators can also be applied to int and long variables.) a = 21 >> 2; This shifts the individual bits of the number 21 two places to the right. Binary 00010101 (21) becomes 00000101, which is 5. Shifting to the right by one bit is equivalent to dividing by two. In this example, when shifting by two places, it is divided by 4, always rounding down. (The decimal part of the division basically corresponds to the bits that are simply discarded as they fall off the right side when shifting.) The empty positions on the left (here the first 2 positions) are always filled with zeros. Negative numbers are an exception, because with char, int, and long types, the first bit being a 1 indicates that the number is negative. If there is a 1, 1s are filled in from the left as the number is shifted right. a = 21 255) // limit PWM to maximum 255 { pwm = 255; } else if (pwm < 0) // PWM at least 0 (not negative) { pwm = 0; } } if (pwm != last_pwm) // if value has changed { analogWrite(pwm_pin, pwm); // modify output signal last_pwm = pwm; }

122

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 119

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

Now the new duty cycle value for the pulse-width modulation is determined. If no current is to flow, the value will be 0. Otherwise, the deviation (nominal value minus actual value) is calculated, and a fraction of it is added to fine_pwm. Tests have shown that a factor of 0.025 is optimal. Depending on whether the current is too low or too high, this share can be positive or negative. The rounded result is now added to the previous PWM value and then subtracted from fine_pwm, so that fine_pwm still contains only a very small value (±0.5). The PWM setting can only be an integer, but the small remainder from the rounding is not lost, and can be taken into account in the next passes. last_pwm is always the PWM value from the previous pass. We check whether this value is 0, which would mean that the current was previously set to 0. In this case, 34 is added to the PWM value. This is how much is needed to reach the transistor’s threshold voltage – lower than that, and no current flows at all. Furthermore, pwm is limited to the allowed range (0 to 255) and, in case of a change (since the last pass) it is output as a PWM signal to the pin. Of course, last_pwm must then be set to the current value for the next pass. if (pwm && pwm < 255) // if switched on and regulation is working { digitalWrite(led_pin, HIGH); // LED on } else { digitalWrite(led_pin, LOW); // LED off } } Now the LED on the board is rapidly controlled. If PWM is not 0, but also not 255 (that means if the current is on and also a load is connected), the LED is turned on, else it is switched off. system_time = millis(); // read current time if (display_time no battery , 1->empty , 2->rising, 3->power, 4->reduced, 5>full, 6->undervoltage, 7->overvoltage byte n = 0; // count variable (for loop passes) byte counter = 0; // count variable (for ri calculation and after charging for text outputs) int pwm = 0; // actual pulse width modulation byte last_pwm = 0; // previous pulse width modulation float fine_pwm = 0; // fine value of pulse width modulation byte led = 0; // LED lighting duration 0 to 200 (also 253 and 254 for errors) byte full_counter = 0; // counts end current until it overflows, then charging is finished byte led_time; // counts every second from 200 back to 0 (for LED control) bool led_on = false; // LED state, true while charging float v_factor = -2; // actual calculated gain factor of T1 (negative is invalid) The other variables are self-explanatory from their comments. void setup() { pinMode(current_pin, INPUT); // Set inputs and outputs pinMode(collector_pin, INPUT); pinMode(supply_pin, INPUT); pinMode(led_pin, OUTPUT); digitalWrite(led_pin, LOW); Serial.begin(38400); // set up serial transfer analogReference(INTERNAL); // use internal reference for ADC current_16_factor = (float(reference) / 65536) / r4; // calculate factors collector_15_factor = (float(reference) / 32768) * (r7 + r8) / r8; supply_15_factor = (float(reference) / 32768) * (r5 + r6) / r6; middle_current = round(sqrt(float(end_current) * power_current)); rb = r1 + r2 + r3 + r_be; // sum base resistors Serial.println(" "); // Output basic settings Serial.println("Settings:"); Serial.print("max "); Serial.print(end_voltage / 1000.0); // end voltage (in volts as float) Serial.println(" V"); Serial.print("max "); Serial.print(power_current); // maximum charging current Serial.println(" mA"); Serial.println(""); system_time = millis(); // system time in milliseconds display_time = system_time + refresh_time; // display time in milliseconds start_time = system_time; // start time in milliseconds } 136

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 133

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

The setup() components are also largely self-explanatory. The three “_factor” variables are calculated from the resistances, among others. They are later used to convert the measured values into the corresponding currents and voltages. void loop() { // Sum actual measurements (and pwm): current_16 += analogRead(current_pin); pwm_13 += pwm; collector_15 += analogRead(collector_pin); current_16 += analogRead(current_pin); supply_15 += analogRead(supply_pin); n++; // count loop passes if (!(n & 31)) // at every 32nd pass { In the loop, the necessary measurements are first performed and all summed up in their corresponding variables. Then, counter variable “n” is incremented, and the next program part is executed after every 32nd pass. The 10-bit values from the analog-todigital converter have been summed up to a 15-bit value over 32 passes, hence the suffix “_15” in the variable names. In current_16, there are 16 bits, because the values are measured and summed up twice during each pass. In pwm_13, the 8-bit PWM values were summed to a 13-bit value. current = current_16_factor * current_16; // calculate actual current collector = collector_15_factor * collector_15; // calculate collector voltage supply = supply_15_factor * supply_15; // calculate board voltage current_16 = 0; // reset values for new (32-fold) summation collector_15 = 0; supply_15 = 0; battery = supply - collector; // battery voltage average_current += current; // sum average values average_supply += supply; // (summations run for 1 second each time) average_battery += battery; average_collector += collector; average_pwm += pwm_13; // also sum PWM values count_average++; // count summations pwm_13 = 0; // also reset Now the program block that’s executed only at every 32nd pass begins. The current, as well as the operating voltage and the collector voltage, are calculated and then again summed up in the corresponding “average_” variables (for one second). The old (summed 32 times) values are then reset.

137

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 134

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

current_limit_2 = set_current + 2; // limits eventual current increase if (supply > over_voltage) // if board voltage is too high { set_current = 0; mode = 7; led = 254; } else if (supply < under_voltage) // if board voltage is too low { set_current -= 1; // reduce current mode = 6; if (supply < under_voltage - 100) led = 253; // only at extreme undervoltage } else if (battery > 4300) // if no battery is inserted { set_current = 0; mode = 0; counter = 0; led = 0; digitalWrite(led_pin, LOW); } else // battery is inserted { if (mode == 0) // if no battery was inserted before { energy = 0; // reset charge start_time = system_time; // start time now } if (battery < empty_voltage) // if battery is empty { set_current = empty_current; // first only minimum current mode = 1; led = 1; // minimum flash duration } else if (battery < power_voltage) // rising phase { set_current = (battery - empty_voltage) / (power_voltage - empty_voltage); led = 2 + (set_current * 48); // 2 to 50 set_current *= (power_current - empty_current); set_current += empty_current; mode = 2; } else if (mode != 5) // if battery is not full yet (still charging) { if (battery power_current) // if current is set too high now { set_current = power_current; // limit to maximum current } if (mode != 4) // if mode for end voltage was not reached already { mode = 3; // set to power mode } } else // final voltage reached { led = 196 - (45 * set_current / power_current); // 151 to 196 set_current -= (battery - end_voltage) / 40; // per mV too much reduce 25 µA mode = 4; // Set mode for final voltage if (current < end_current) // end current undershot (finish charging) { full_counter++; // increase counter for switch off if (!full_counter) // in case of overflow (switch-off) { // Battery full: set_current = 0; led = 200; // stays on digitalWrite(led_pin, HIGH); mode = 5; // charging finished end_time = millis(); } } else if (full_counter) // if current flows but full counter is already set { full_counter--; // count back } } } 139

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 136

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

} if (set_current > current_limit) set_current = current_limit; // limit current if (set_current > current_limit_2) set_current = current_limit_2; if (set_current < 0) set_current = 0; // current can not be negative average_set += set_current; // summing average values for setpoint current In this lengthy section, the current mode, “mode,” is determined depending on the battery voltage and the setpoint current set_current is adjusted. In addition, the variable “led” is assigned a value of between 0 to 200, depending on the battery’s charge state. if (!set_current) // if no current setpoint (zero) { pwm = 0; // no pulses } else // current shall flow { fine_pwm += (set_current - current) * 0.07 * r4; pwm += round (fine_pwm); // change PWM by integer value fine_pwm += last_pwm - pwm; // subtract change (leave only +/- 0.5) if (pwm > 255) // limit PWM to maximum 255 { pwm = 255; } else if (pwm < 0) // PWM at least 0 (not negative) { pwm = 0; } } if (pwm != last_pwm) // if value has changed { analogWrite(power_pin, pwm); // modify output signal last_pwm = pwm; } } The current PWM value is determined here. If no current is to flow, the value is set to 0. Otherwise, the difference between the current setpoint and the actual current is first determined. (Depending on whether the current is too low or too high, the result may be positive or negative). Then, a small portion of this is added to fine_pwm (a float variable). The actual PWM value is then changed to the rounded integer, while this integer is then subtracted from fine_pwm, leaving only a small value in the range of ±0.5, which is again taken into account in the next pass.

140

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 137

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

system_time = millis(); // read actual time led_time = 200 * (display_time - system_time) / refresh_time; // led_time decreasing from 200 to 0 (within 1s interval) if (led > 0 && led < 200) // if LED in normal flash mode { if (!led_time) // if time elapsed to 0 { digitalWrite(led_pin, LOW); // LED off led_on = false; } else if (led >= led_time && !led_on) // if time to LED value elapsed { digitalWrite(led_pin, HIGH); // LED on led_on = true; } } else if (led == 253) // if error (undervoltage, fast blinking) { led_time -= 50 * (led_time / 50); // 4 time units (49 to 0 decreasing) if (led_time == 20) // on at 20 { digitalWrite(led_pin, HIGH); } else if (!led_time) // off at 0 { digitalWrite(led_pin, LOW); } } else if (led == 254) // if error (overvoltage, very fast blinking) { led_time -= 25 * (led_time / 25); // 8 time units (24 to 0 decreasing) if (led_time == 9) // on at 9 { digitalWrite(led_pin, HIGH); } else if (!led_time) // off at 0 { digitalWrite(led_pin, LOW); } } Here, the LED blinking is controlled. To do this, led_time is first determined, a value that continuously decrements from 200 to 0 for one second between the data outputs (coming up in the next section). By comparing “led” with led_time, the blinking is controlled in such a way that the light duration corresponds to the value “led.” In case of an undervoltage error (led == 253) the LED flashes quickly. With overvoltage (led == 254), it flashes even faster.

141

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 138

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

if (display_time = 0.05) // if still charging or current is still flowing { // calculate further values based on average values: ue = average_current * r4; uce = average_collector - ue; ib = ((average_supply * average_pwm / 8160) - (ue + u_be)) / rb; if (uce < 120 + (average_current / 2.5) || average_pwm > 8000) // saturation { v_factor = -1; // invalid (because of saturation) ic = average_current - ib; // collector current = emitter current - base current } else if (ib < 0.5/r4) // Base current too small (and thus too inexact) to calculate { v_factor = -2; // invalid (because inexact) ic = average_current * 0.99; // collector current estimated (ampl. factor 100) } else // base current and amplification factor calculable { ic = average_current - ib; // collector current = emitter current - base current v_factor = ic / ib; // amplification factor } energy += round(refresh_time * ic / 60); // charge in µA min (add 1 second)

142

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 139

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

If the battery is not yet completely charged, the collector current and the transistor’s amplification factor are determined as accurately as possible. For example, if the current is small or if the transistor is (almost) in saturation, no amplification factor can be determined. Finally, the charged energy or the total charged current is updated. The unusual unit, microampere minutes (instead of milliampere hours) makes sense only because the “energy” variable is of type unsigned long in order to have values as accurate as possible, but to still be able to cope with large batteries of several ampere hours without overflowing. pt1 = average_current * uce / 1000; // T1 Power dissipation in mW pr4 = average_current * ue / 1000; // R4 Power dissipation in mW if (pt1 > p_t_max) // power overload (transistor) { current_limit_2 = float(p_t_max) * 1000 / uce; // limit power dissipation } else { current_limit_2 = 9999; // do not limit } if (pr4 > p_r_max) // power overload (R4) { current_limit = sqrt(float(p_r_max) * 1000 / r4); // limit power dissipation } else { current_limit = 9999; // do not limit } if (current_limit_2 < current_limit) { current_limit = current_limit_2; // use smaller limit } Now, the current power dissipation (over the last second) in T1 and R4 is determined, and, if necessary a limit variable is set to reduce the current. It’s sufficient to do this only once per second, because the power dissipation can only increase slowly, and a brief, slight overrun wouldn't do any harm, either.

143

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 140

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

duration = (system_time - start_time) / 1000; // duration since charging start if (duration > 900 && average_current > 50 && average_battery > end_voltage 200 && !counter) { // Start measurement of internal resistance Ri: last_current = average_current; // save values for later use last_voltage = average_battery; ri = 0; // reset for summation counter++; // counts seconds for 1 minute (as long Ri measurement runs) current_limit = 0; // switch off charge } else if (counter < 59 && counter) // while measurement is running (1 to 58) { if ((counter&3) == 1) // Second 1, 5, 9, 13, 17 ... { current_limit = 0; // keep switched off } if ((counter&3) == 2) // Second 2, 6, 10, 14, 18 ... { ri+= (last_voltage - average_battery) / (last_current - average_current); set_current = last_current + 10; // set high (avoid limitation) last_current = average_current; // save values to use later last_voltage = average_battery; // (current should be 0 here) current_limit = 9999; // switch on again } else if (!(counter&3)) // Second 4, 8, 12, 16, 20 ... { ri+= (average_battery - last_voltage) / (average_current - last_current); last_current = average_current; // save values to use later last_voltage = average_battery; // (current should flow here) current_limit = 0; // switch off again } counter++; // count up one second } else if (counter == 59) // finish measurement after 59 seconds { ri /= counter >> 1; // divide by number (half counter value, rounded down 29) counter++; // to 60 } days = duration / 86400; // calculate single values from total duration duration -= days * 86400; hours = duration / 3600; duration -= hours * 3600; minutes = duration / 60; duration -= minutes * 60; seconds = duration;

144

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 141

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

If the charging process has (900 seconds), and a minimum already reached 200 mV, and determined, then the resistance

been running for at least a quarter of an hour current of 50 mA is flowing, and the final voltage has the internal battery resistance has not yet been measurement begins.

In the simplest case, the internal resistance of a current source may be determined from its open-circuit voltage and short-circuit current, but, in most cases (including here) this would not be a good idea at all, because I’ve made stranded wires glow in fractions of a second with accidental short circuits on lithium-ion batteries. This is not something you do on purpose. Fortunately, there’s a gentler method: changing the charge or discharge current, and measuring the voltage change across the battery. For one minute, we switch off every two seconds, then charge, then switch off… etc. The current and voltage differences are summed up, and finally the battery’s internal resistance is calculated. Then, second-counter “duration” is briefly converted into longer time units, which are needed in the following section for the output. // Output relevant data and average values of the last second: Serial.println(" "); Serial.print("Charge: "); Serial.print(float(energy) / 60000, 3); // µA minutes to mAh, 3 decimal places Serial.print(" mAh "); if (days) // only if at least 1 day already elapsed { Serial.print(days); Serial.print("d:"); } if (days || hours) // only if at least 1 hour already elapsed { if (hours < 10) // if value is only one digit { Serial.print("0"); // prefix "0" } Serial.print(hours); Serial.print("h:"); } if (minutes < 10) // if value is only one digit { Serial.print("0"); // prefix "0" } Serial.print(minutes); Serial.print("m:"); if (seconds < 10) // if value is only one digit { Serial.print("0"); // prefix "0" 145

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 142

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

} Serial.print(seconds); Serial.println("s"); Serial.print("Bat: "); Serial.print(average_current, 1); // current with one decimal place Serial.print(" mA "); Serial.print(average_battery / 1000); // battery voltage in volts Serial.print(" V Ri: "); if (counter < 60) { Serial.println("???"); // Ri not determined (yet) } else { if (ri >= 1) // 1 ohm and above { Serial.print(ri); // output in ohms (by default with 2 decimal places) Serial.println(" Ω"); } else // below 1 ohm { Serial.print(round(ri * 1000)); // output in milliohms (no decimal places) Serial.println(" mΩ"); } } Serial.print("Set: "); Serial.print(average_set, 1); // current setpoint Serial.print(" mA "); Serial.print(end_voltage / 1000.0); // final charge voltage (in volts as float) Serial.println(" V (maximum)"); Serial.print("Board: "); Serial.print(average_supply / 1000); // actual board voltage Serial.print(" V Status: "); if (counter < 60 && counter) // during Ri measurement { Serial.println("Get Ri"); // show info as status } else if (mode == 1) // otherwise depending on current mode { if (battery < empty_voltage - 300) Serial.println("Totally empty"); else Serial.println("Battery empty"); } else if (mode == 2) { Serial.println("Nearly empty"); } else if (mode == 3) { 146

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 143

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

Serial.println("Half full"); } else if (mode == 4) { if (set_current < middle_current) Serial.println("Nearly full"); else Serial.println("Soon full"); } else if (mode == 5) { Serial.println("Full"); } else if (mode == 6) { Serial.println("U_Board LOW"); // undervoltage } else if (mode == 7) { Serial.println("U_Board HIGH"); // overvoltage } else if (!mode) { Serial.println("No battery"); } Serial.print("PWM: "); Serial.print(average_pwm / 81.6); // 0 to 100% (max. 255 x 32 = 8160) Serial.print("% LED: "); if (led > 200) // display error { Serial.println("Fast"); } else { Serial.print(led * 0.5, 1); // light duration of blinking in percent Serial.println("%"); } Serial.print("T1: "); // Transistor info: Serial.print(round(pt1)); // power dissipation in mW Serial.print(" mW Uce: "); Serial.print(round(uce)); // voltage between collector and emitter (in mV) Serial.print(" mV Ic/Ib: "); // amplification factor if (v_factor == -1) { Serial.println("Sat"); // transistor (possibly) in saturation } else if (v_factor == -2) { Serial.println("???"); // current too small for exact measurement } else 147

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 144

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

{

}

Serial.println(round(v_factor)); // amplification factor } Serial.print("R4: "); // Info about R4: Serial.print(round(pr4)); // power dissipation Serial.print(" mW "); Serial.print(round(ue)); // voltage (in mV) at R4 Serial.print(" mV T1+R4: "); Serial.print(round(pt1 + pr4)); // Total power dissipation in mW (T1 and R4) Serial.println(" mW"); Serial.println("");

Here, the current data is output serially as text, once per second. else // If battery is full and no more current is flowing: { if (counter > 10) counter = 0; // reset (old value from Ri measurement) if (counter < 8) // if not all 8 infos have been displayed yet if (millis() >= end_time + long(control_time[counter]) * 60000)// info time { if (!counter) // First info (after 1 minute) if counter is still at 0 { full_voltage = average_battery; // save actual voltage Serial.print("Fully charged: "); Serial.print(full_voltage / 1000,3); // voltage indication with 3 decimal places Serial.println(" V (after 1 min)"); } else // if first info was already displayed { Serial.print("Self-discharge: "); Serial.print(round(full_voltage - average_battery)); // voltage loss in mV Serial.print(" mV after "); Serial.print(control_time[counter]/60); // calculate number of hours if (counter == 1) Serial.println(" hour"); // singular else Serial.println(" hours"); // or plural } counter++; // count on for next message } } This part is executed when the battery is already full. After one minute, the battery voltage is displayed. After 1, 2, 4, 8, 16, 32, and 64 hours (if you leave the battery in for that long) it shows how much the battery voltage has decreased since charging. The counter for the individual outputs is the same “counter” variable that was used previously for measuring the internal resistance.

148

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 145

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

average_current = 0; // reset all average values for new summation average_supply = 0; average_battery = 0; average_collector = 0; average_set = 0; average_pwm = 0; count_average = 0; // reset also the number of summations } } Finally, the “average_” variables and the corresponding counter variable are reset and ready for the next second’s values.

Current and voltage specifications Besides the exact resistor values in the sketch’s definitions, there are also numerous variables given in the first two variable blocks, where we can place all the necessary current and voltage settings: int end_voltage = 4200; // final charging voltage in mV The final charge voltage for lithium-ion batteries is usually 4.2 V, i.e. 4200 mV. Ideally, this voltage should not be exceeded (or only slightly, by max. 50 mV). However, there are also types which may be charged a little higher. If, on the other hand, you do not need the full capacity, you can save the battery and charge it only up to 4.1 V or even up to 4.0 V. int power_current = 400; // maximum charging current in mA This determines the maximum charging current. However rather than always flowing at the full rate, but it is done according to exact parameters. A total of 6 variables determine the exact charging curve.

149

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 146

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

The graph shows the voltage horizontally and the charging current vertically (from the black zero line):

Fig. 8.5f: Charging curve If the battery is completely empty – i.e. below empty_voltage (2.8 V) - only a minimum current of empty_current (20 mA) flows at first. As soon as voltage empty_voltage is reached (which happens very quickly), the charging current increases continuously up to a level of power_current (400 mA) at a voltage of power_voltage (3.7 V). This voltage is also usually reached relatively quickly. Now, the actual main charge cycle begins with a constant current of power_current (400 mA), until final voltage end_voltage (4.2 V) is reached. Then the current is continuously reduced so that the final voltage is not exceeded, but is maintained. What seems like just a moment in the graph (denoted by a vertical line at the end of the charging process), can take a very long time in reality. Only when the current has reduced to end_current (10 mA), is the current switched off completely and the charging process is complete. Thereafter, the battery voltage can drop minimally again. In the graphic, this point (no more current after charging, and almost at the end voltage) is shown as a red dot. The value end_current can also be set higher if the charge is to be terminated sooner. Usually it’s 5% or 10% of the maximum current, for example. That would be 20 or 40 mA. The battery voltage is then marginally lower at the end. But you could just as easily remove the battery earlier. It would then not be completely charged, but maybe only at 95%. However, the current curve during charging (especially the maximum current, power_current) can also be reduced by other factors, e.g. when the transistor reaches saturation, or when the operating voltage via USB is not very stable and drops to the undervoltage limit. Likewise, the current is limited when the power limit for transistor T1 or resistor R4 is reached. However, all this is usually not bad. We don't necessarily have to reduce the power_current setting for this reason, because the current is automatically reduced to such an extent that everything is back in the green zone. Also, the measurement of the 150

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 147

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

charged milliampere hours is not rendered inaccurate by this. Only the actual current always counts. In p_t_max and p_r_max, we can specify the maximum power dissipation of T1 and R4. The transistor can handle about 1 watt uncooled, as does 1-watt resistor R4. However, to be on the safe side, we limit the power dissipation to 750 mW each. If a heat sink is used for the transistor, we can increase p_t_max (depending on the size of the heat sink) to 2, 3, or 4 watts.

Serial output This is what the output looks like in Serial Monitor. The baud rate must be set to 38400. The window shows the display a few hours after charging. The upper seven lines are updated every second as long as the battery is charging. When the battery is full, the lower lines appear, gradually. In the first line, you see the total charged current in milliampere hours, as well as the charging duration.

Fig. 8.5g: Serial Monitor output

The second line shows the currently-flowing charge current, the current battery voltage and the internal battery resistance, if this has (already) been determined. In the third line are the setpoints: first the charge current that we’re aiming for (it should correspond to the actual current, if the transistor is not in saturation), then the desired final voltage. Incidentally, the actual current and the setpoint always refer to the emitter current. This facilitates calibration. However, the actual charge current from the collector is used to calculate the charge in mAh. This is about 1% smaller. The fourth line shows the current board supply voltage, as well as the current status, which usually corresponds to the state of charge or the charge cycle, but it also notifies us of events such as over- or undervoltage. 151

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 148

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

The fifth line shows the current PWM setting. This is usually between 10 and 50 percent. (At significantly higher values, the transistor is in saturation.) After this, the LED-blinking duty cycle is shown. At 0%, the LED is always off, at 50% it’s on as long as it’s off, and, at 100%, always on. In the sixth line we find the information about the transistor. First, the current power dissipation in T1, then the collector-emitter voltage (Uce), then the amplification factor, if it can be currently determined. The seventh line contains the power dissipation in resistor R4, then the voltage at the resistor, and at the end, the total power dissipation of T1 and R4. After charging, the battery voltage is displayed after one minute, which should then be very slightly below the final voltage, for example 4.192 volts, as can be seen in the output window. Then, after 1, 2, 4, 8, 16, 32, and 64 hours (should you leave the battery connected for that long), you will see how far the battery voltage has decreased from the original voltage (which was initially measured after one minute). This voltage drop, which is ideally only a few millivolts after a few hours, says a lot about the quality and the condition of the battery. However, an initial drop of a few millivolts in the first hours is still OK if this value slows afterwards, else it means that the battery probably has a high self-discharge and its best days are over. The most important quality criterion, however, is the milliampere hour number. With lithium-ion batteries, the charge that can be consumed from the battery is hardly any less than the charge that it takes back when charging. So, if a really empty battery (and by that I mean when the voltage is around 3 volts) is fully charged (usually up to 4.2 volts) then the displayed charge in mAh should also correspond relatively accurately with its actual capacity. Another quality criterion is the internal resistance:

Internal resistance If a battery is under load, its voltage always drops a little. By this I don’t mean the discharge, because if you remove the load, the battery immediately returns to its original voltage, to a large extent. When charging, it’s the other way around. The voltage rises immediately a little, but goes back down again when you remove the charging current. The reason for this is the internal resistance. We can think of a real battery as something like an ideal battery with a small resistor in series.

Fig. 8.5h: Actual battery

152

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 149

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

We can measure this resistance from the voltage changes that occur when the current changes. To do this, the device (after at least 15 minutes of charging, and if it’s no more than 200 mV below the final voltage) switches the charging current off and on repeatedly, for periods of 2 seconds each, over the course of one minute. The internal resistance of larger lithium-ion batteries should ideally be well below one ohm. If the value is higher, this could also be due to the charger’s contacts. Cheap battery holders (for example for 18650 cells) often already have a devastating contact resistance of more than one ohm, which of course also factors into the measurement. Perhaps the bigger problem is that charging at high resistance takes much longer. The final voltage seems to be reached faster, but the battery is far from full, because the voltage drops at the contacts. The current is reduced earlier and to a greater degree, and charging takes longer. If neither this nor the falsified internal resistance bothers us, we can use a cheap battery holder. Otherwise, one with gold-plated contacts is preferable.

Calibration Accurate calibration is very important here. Therefore, we carry it out in two steps to be on the safe side. Uncalibrated, the values could deviate by up to 10%. In extreme cases, a battery could be charged up to 4.62 volts, and it would not forgive that. First of all, we have specified the program sketch above. half-empty) battery. What’s because this could still be set

the internal reference voltage at an estimated 1100 mV in With this, we can now simply charge an (empty or important is that the final voltage is not yet reached, too high when uncalibrated.

Now, we use Serial Monitor, which shows us the values every second. While we keep an eye on the current, we measure the voltage at R4 with an accurate multimeter, in its millivolt range. Then we can do the math: reference = reference_old  actual_voltage / R4 / Monitor_current reference_old is the previous reference specification (1100). The actual_voltage is the voltage at R4, which we measure using our multimeter. R4 is the resistance value itself, i.e. in ohms. Monitor_current means the current that Serial Monitor shows us in the second line. We now enter the result (rounded to the nearest integer) as the new reference value in the sketch and load it onto the board. It must be between 1000 and 1200, else something is wrong.

153

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 150

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Once we have made this adjustment and uploaded it to our board, we now take care of the most important value, which needs to be the most accurate – the battery voltage. Here, too, we should use an accurate multimeter. But we don’t measure at the battery directly, rather at the corresponding connections on the board, i.e. B+ and B-. Then we can calculate again: reference = reference_old  actual_voltage / Monitor_voltage Note: reference_old is now no longer 1100, but the already-changed value. The actual_voltage is again the voltage measured using multimeter, this time at B+ and B-. Monitor_voltage is the battery voltage shown in Serial Monitor, on the second line. Both voltages should now (after the first calibration) differ only slightly, so that, in the equation, almost the same value is calculated again. The new value is optimized for the measurement of the battery voltage, because this must be the most accurate. We can also enter the higher of the two calculated reference values in the sketch, and thus ensure that neither the charging voltage nor the charging current are higher than specified. If the two values differ by more than 3 percent, there is either an error or the resistors have too much tolerance.

Usage The charging station is now ready for use. In Serial Monitor we can observe the charging process. Later, if everything works as it should, we can also use the circuit as a simple charger (without the serial connection). Then, the LED on the board shows us the most important information: If it’s off, no battery is inserted; if it’s constantly on, the battery’s full; if it flashes, the battery is being charged. The duration of its flashing gives us information about the charging status. If it flashes only briefly, for example, the battery is empty. If it lights up almost all the time and only goes out briefly, the battery is almost full. In the event of an undervoltage error, it flashes rapidly, and, for overvoltage, very rapidly, but I do not recommend testing this. Since there is still plenty of memory left in the ATmega328, the circuit can be expanded as desired. With a display (e.g. a 2004 LCD display) and button(s), we could, for example, set the power_current and end_voltage variables in steps within setup(). The program block performing the serial outputs could be replaced by one sending output to our display. In this way, we would have a completely independent device, using a display, as in section 11.3 on page 250.

154

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 151

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

8.6 Project: Adjustable current source with limits With the same construction as the charging station (section 8.5) we can also create a universal current source, which can be used almost like an adjustable laboratory power supply. The circuit can be operated with voltages up to 31 volts. For this, only two resistors (R5 and R8) have to be re-specified. In addition to an adjustable current, the voltage and/or the power of the load can also be limited to a predefined value here.

Component specification Voltage

R5

R8

C3

Max. 5.5 V

22 k

220 k

Max. 6.5 V

27 k

180 k

Max. 7.5 V

33 k

150 k

Max. 9.0 V

39 k

120 k

max. 11 V

47 k

100 k

Voltage

max. 13 V

56 k

82 k

depends

max. 15 V

68 k

68 k

on max.

max. 18 V

82 k

56 k

operating

max. 22 V 100 k

47 k

voltage

max. 26 V 120 k

39 k

max. 31 V 150 k

33 k

1000 µF

A significant difference is resistors R5 and R8, because these must now be chosen according to the maximum used operating voltage per the table. In addition, we must ensure that electrolytic capacitor C3 can handle the operating voltage. For R4 here, 1 ohm / 2 watts is provided, which allows for the control of a maximum current of 1 amp. For other ranges of current, we can use the table on page 118. For higher currents and high voltage differences between input and output, a larger heat sink for T1 is required, whereby the permissible T1 power dissipation in the sketch must be adjusted.

Time vs charge amount In addition, the program also offers the ability to limit the delivered current to a certain duration or a predefined charge quantity (in milliampere hours). This can be very useful when charging NiCd, NiMH, or lead-acid batteries, because there, the charging process is not as simply limited by voltage. Instead, it usually makes more sense to limit the charge amount to the required mAh value. Once this charge amount is reached, the program simply switches the circuit off. Of course, this circuit can still not completely replace a high-quality laboratory power supply. For constant loads (such as incandescent lamps, heating elements, power LEDs, etc.) the regulation works very well, as well for charging rechargeable batteries and for controlling motors. But, strictly speaking, only the current is directly controlled by this current source.

155

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 152

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

All other adjustments, such as voltage limitation, are made (as quickly as possible) via the current setting, so care should be taken with loads containing internal electronics that can change their current consumption quickly. A sudden drop in current consumption can cause a brief overvoltage. The output voltage becomes a bit more stable if we add an additional 1000 µF capacitor and 1 kΩ resistor in parallel to the output – i.e. in parallel to the load. This resistor should be able to handle of a load of 1 watt. (Up to 20 V, a ½ W is sufficient, and for up to 15 V, ¼ W suffices.) However, these parts are not yet included in the basic circuit diagram:

Fig. 8.6a: Circuit diagram, adjustable constant current source The circuit diagram is almost identical to that of the charging station. Instead of the battery we now have another load (which could also be a battery, e.g. a 12 -volt lead-acid battery). Instead of the 5-volt operating voltage, we now have a variable operating voltage, which can also be higher – up to a maximum of 31 volts, and instead of the dashed connection between the total operating voltage and VCC, we now have a dashed connection to RAW. This means that there must be no connection from RAW to VCC, and the connection to RAW must be disconnected if the operating voltage is higher than 12 volts. In that case, the Pro Mini board needs a separate supply (5 to 12 volts) to RAW. Ideally, in the PCB version, you mount the Pro Mini on the RAW pin not with a continuous pin strip, but with 2 shorter ones, whereby RAW is simply left out if it is not to be connected. Or just snip off the RAW pin on the header beforehand, on the side with the shorter pins, so that it is soldered to the board but still missing from the board. If necessary, we can also cut the trace on the board between RAW and the connector pin directly in front of it – but, as I said, only if we use more than 12 V. 156

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 153

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

Sketch: Adjustable current source with limits #define #define #define #define #define #define #define #define #define #define #define

8_6.ino

current_pin A0 collector_pin A1 supply_pin A2 power_pin 5 led_pin 13 r4 1.00 // 1W up to 800mA or 2W up to 1A r5 56000 // up to 13 Volt r6 4700 r7 1000000 r8 82000 // up to 13 volts reference 1100 // internal reference voltage, calibrate!

Here again the pins used, the resistors and the reference voltage are first defined. R5 and R8 must be adapted to the maximum used operating voltage, according to the table. R4 can be adapted to other current ranges. The reference voltage must also be calibrated here. int max_voltage = 12000; // limit load voltage (12 volts) int max_current = 300; // limit load current (0.3 amps) int max_power = 2000; // limit load power (2 Watt) int max_charge = 0; // limit load charge in mAh (0 = unlimited) unsigned int max_time = 0; // max. time in seconds (0 = unlimited, max. 65535) int p_t_max = 750; // maximum power dissipation (in mW) in the transistor int p_r_max = 750; // maximum power dissipation (in mW) in R4 boolean on = true; Then come the variables that control the output current. For the connected load, we can limit the voltage, the current, the power, the amount of charge delivered, and/or simply the time. p_t_max indicates how much power dissipation the transistor can handle, and p_r_max is the maximum power dissipation we expect resistor R4 to handle. In addition, it is easy to add your own program sections later in the loop, in order to modify the variable values and thus to control the output.

157

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 154

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

[..] void setup() { [..] } void loop() { [..] } The rest of the program is self-explanatory, thanks to the comments, and is also partly identical to sketch 8.5, or at least similar. Therefore it has not been printed in its entirety here. Instead, I would like to explain only the main change, briefly: To limit the individual values, there are now a few more “set_” variables in addition to the target current, set_current, for the individual limits according to which the current is controlled. The smallest value (i.e. the strongest limitation) is set as set_new and then adopted as the new set_current.

Power supply The operating voltage should be about 1 to 2 volts higher than the maximum required output voltage, but, not higher than necessary if possible, because a quick adaptation to changing loads is not possible with this simple circuit, so a brief overvoltage could occur in the case of a sudden discharge. If the operating voltage exceeds 12 volts, the connection to the board’s RAW connector must be disconnected and the board must be supplied with a separate voltage (5 to 12 volts, min. 100 mA) at the RAW connector. Of course, the power supply must also be able to deliver the required current.

Serial output Here, the first line shows the present values for voltage, current and power consumption in the load. The corresponding preset limitations are directly below. The third line shows the data for the current operating voltage, PWM duty cycle, and the current operating mode. Fig. 8.6b: Serial output 158

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 155

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

The fourth line shows the transistor’s power dissipation, the voltage between collector and emitter at the transistor, and the power dissipation in resistor R4. Then, the second-last line shows the charge delivered so far. If there is a limit, it is shown in parentheses. The last line shows the elapsed time, and, if this has been limited in the settings, the remaining time is shown next to it. If this time has elapsed or the charge amount has been reached, the device switches off automatically. A restart is possible at any time using the reset button. Time and charge quantity are then reset. The table on the left shows the various operating mode abbreviations displayed in the 0 turned off OFF Serial Monitor. OFF means switched off or that the “on” variable is set to 0 or “false.” CV 1 constant voltage CV (constant voltage) limits the voltage. CC 2 constant current CC (constant current) limits the current, and with 3 constant power CP CP (constant power) you can also specify the power in the load. You only have to set voltage 4 short-circuit SC and current a little higher (or not limit them at 5 overload OL all, using 0). Then, the load is regulated to the 6 saturated transistor SAT specified power. SC (short circuit) is displayed when the voltage at the load is below one volt 7 undefined UD with current limitation. OL (overload) means that the transistor (or resistor) is at its load limit, and therefore the current is reduced. SAT (saturation) is indicated when the desired limit cannot be reached at all, because the transistor is in saturation and is therefore being fully-driven without reaching the current, voltage, or power limit. The operating voltage is then too low, because the output voltage is only marginally lower than it. Mode

Description

Abbr.

Should all of this not be the case, status UD (undefined) is displayed. This may be the case for a short time, for example, if a load has just been connected. The current then increases, but is not limited by anything in the first moment.

Cooling Without additional cooling, the transistor’s internal power dissipation should be limited to 750 mW. For the charging station (section 8.5) this was no problem, because the difference between input and output voltage there was relatively small. This could be different here. If the output voltage is significantly lower than the operating voltage, and a high current flows, then a larger heat sink is necessary.

159

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 156

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

If a heat sink is used, we have to increase the p_t_max value in the sketch accordingly. To do this, we first enter a higher value (e.g. 8000 for 8 watts). Then we do a load test where Serial Monitor shows more than 1 watt power dissipation in the transistor. This way we can test the heating. If the transistor does not get too hot, we run the load test for half an hour or more, and measure the temperature at the transistor. An infrared thermometer such as the one on page 45 is ideal for this. Unfortunately, with a finger on the transistor, the temperature can only be estimated very roughly. It may well become hot. If you put a small drop of water on the labeled surface of the transistor, it should not evaporate immediately. An increase in temperature of 75 degrees (e.g. running at 100 degrees from a room temperature of 25 degrees) is the maximum permissible limit. For example, if we have an increase of only 25 degrees at 2 watts, we can allow a maximum of 3 times that, or 6 watts, and enter the value 6000 in the sketch. If the circuit is later placed in an enclosure, this again has a detrimental effect on cooling.

Default values, limits With variables max_voltage, max_current, max_power, and max_charge, we can limit the voltage, the current and/or the power, as well as the charge amount at which the charging circuit is to be switched off, if necessary. For values that we do not want to limit, we simply enter 0. Current and voltage limits are then automatically set (in setup()) to the maximum permissible values, and there is no limit at all for power and charge amount. However, at least one of the first three values must also be sensibly limited, because otherwise current and voltage would theoretically have to run toward infinity. The power dissipation in transistor T1, p_t_max, and in resistor R4, p_r_max, (both not to be confused with the load power, which is limited using max_power) must be adjusted as necessary. For the transistor you can increase the value significantly if you give it additional cooling with an aluminum plate. For the resistor, you can enter 75% of the allowed power dissipation, i.e. 750 for a 1-watt resistor or 1500 for a 2-watt. This way, we’re on the safe side and the resistor can’t get too hot. The “on” variable must be set to “true” in order to enable the power source. If you extend the sketch with your own program sections, you can use this variable to switch the current on and off. If a charge limit is specified, this variable is automatically set to “false” when the charge amount is reached.

160

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 157

2022-07-27 20:20

Chapter 8 • Controlling, regulating, and dimming

Calibration As with all applications where precise voltages or currents are required, a calibration must be performed, because in each ATmega chip the internal reference voltage can deviate by up to ±10%. Calibration is basically the same as for the (almost identical) charging station from the previous chapter (section 8.5). Here, too, there are two possibilities for calibration, by voltage and by current, and I recommend carrying out both. With the second calibration, the calculated reference voltage should only deviate minimally. This way we know that we’ve done everything right. First, in the program sketch, the reference voltage is specified as 1100 mV. With this, we start the current source with any load and measure the voltage at R4 with an accurate multimeter. At the same time, we observe the current we get in the Arduino IDE’s Serial Monitor. Then we can calculate: reference = reference_old  actual_voltage / R4 / Monitor_voltage reference_old is the previous reference specification (1100). actual_voltage is the voltage at R4, which we measure using our the multimeter. R4 is the resistance value, and Monitor_current means the current that the serial monitor shows us in the first line. We now enter the result (in millivolts rounded to the nearest integer) as the new reference value in the sketch. It must be between 1000 and 1200. When we have adapted the reference setting and loaded it onto the board, we measure and calibrate the output voltage for control. For this we first need a stable voltage at the output. This can be done, for example, by charging a battery with a low current setting or by connecting another load together with a large electrolytic capacitor (at least 1000 µF). Ideally, the output voltage should be at least half of the operating voltage. Then we can measure and calculate accurately: reference = reference_old  actual_voltage / Monitor_voltage Attention: If we have already performed calibration, reference_old is now no longer 1100, but the already-changed value. The actual_voltage is, again, the voltage measured with the multimeter, which we now best measure not at the load, but directly at the circuit, at the B+ and B- terminals. Monitor_voltage is the output voltage, which Serial Monitor shows us in the first line.

161

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 158

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

.

Both voltages (measured and displayed) should now (after the first calibration) only differ slightly, so that in the equation almost the same value comes out again. But now we do not enter the new value in the sketch as reference, but the average value from both measurements. This way we have the best possible accuracy for all values that are measured and controlled. We can also enter the higher of the two calculated reference values in the sketch, and thus ensure that neither the output voltage nor the current are higher than displayed. If the two values differ by more than three percent, there is an error or the resistors have too much tolerance.

Usage After calibration, the circuit is ready for use. We can, for example, operate power LEDs (with a 9 to 12 V operating voltage) with a precisely specified power max_power or with constant current max_current. The same applies to mini soldering irons (with a 12 V operating voltage) or other heating elements. NiCd, NiMH, and lead-acid batteries can also be charged using this circuit. The voltage limit is the maximum voltage that can or should be reached during charging. For a 12 V lead-acid battery, this would be about 14 to 14.5 V, and, for a 6 V battery, about half that. For NiCd and NiMH batteries, it is 1.45 V, or a multiple of this if we charge several cells in series. For the current limit, we enter the recommended charge current for charging batteries. We omit out the power limit (i.e. enter 0), and for charge quantity max_charge, we enter (for an empty battery) the battery capacity, or, depending on the recommendation perhaps somewhat more. You can also enter a fixed time for max_time instead of the charge quantity. However, we have to convert this into seconds – i.e. multiply the hours by 3600, or the minutes by 60. DC motors can also be controlled in this way. The set voltage determines the speed. The force (i.e. the torque) can be controlled via current limitation, and the power using power limitation. For example, a motor with strong current limiting has hardly any power, even if it runs at no load much faster than without current limiting at low voltage. Much more about the control of motors can be found in the next big chapter:

162

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 159

2022-07-27 20:20

Chapter 9 • Controlling motors

Chapter 9 • Controlling motors

Fig. 9:

Motor with gears

and

mini stepper motor

With motors, we first have to distinguish between a few basic types. If you simply want to convert electrical power into motion, you usually have to deal with normal DC motors. However, there are also stepper motors, for example, whose positions can be controlled very precisely. These are used in CNC devices, 3D printers, etc. Brushless motors, on the other hand, are very effective and wear-resistant – for high performance in the smallest space.

9.1 DC motors DC motors are, as the name suggests, operated on direct current or direct voltage. If you reverse their polarity, they change their direction of rotation. To control such a motor, an ordinary transistor is sufficient for the simplest case. But, first we should be clear what exactly we want to do, e.g. do we need to run it in both directions? And, is it enough to just switch the motor on and off, or is speed control also necessary?

Fig. 9.1: Two DC motors

9.1.1 Transistor control From page 101 in sections 7.2.3 and 7.2.4, we already got familiar with different transistors, and these are able to switch common DC motors. We can use MOSFETs or bipolar transistors. The picture on the next page shows three examples. 163

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 160

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Fig. 9.1.1: Switching and controlling motors with MOSFETs or bipolar NPN transistors I recommend the version on the far left because it’s the simplest. With a MOSFET you can also switch loads of several amps very easily. The dotted resistor switches off the MOSFET, if the Arduino pin is not set as and output. During reset, the pin might be set as an input, for example. In contrast to the middle circuit, this ground resistor is connected directly to the Arduino, so that the MOSFET’s switching voltage is not reduced. The middle circuit shows a simple example with the well known BD435 from section 7.2.3. If the motor needs more than 1 A, we should increase the base current with a second transistor (BC547 or BC337) as in the example on the right. The BD435 then also needs a small heat sink. But the current should not go above 4 A. The BD435 might not forgive us for that. All three circuits have a diode in parallel to the load, i.e. to the motor, a so-called freewheeling diode, which we’ve also seen before, namely with the relay in section 7.3. Like a relay, a motor is also an inductive load. The diode protects the transistor from voltage spikes (when switching off) and thus also enables clean PWM control.

9.1.2 Speed control using PWM If we want not only to switch the motor, but also control its speed, this can be done very well using pulse-width modulation (PWM). Instead of supplying the motor a lower voltage, we simply switch it on and off several hundred times per second, as already described in section 8.1 on page 108. We use one of the board’s PWM-capable pins (preferably 3, 9, 10, or 11) for this. Using the analogWrite() function, we can then control the speed as we like – from 0 for off to 255 for full-speed. The transistor circuits described here also all suitable for PWM. 164

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 161

2022-07-27 20:20

Chapter 9 • Controlling motors

9.1.3 Forward and reverse with an H-bridge It gets a bit more complicated if we want to control a DC motor in both directions, because for this we need a so-called H-bridge. The picture shows symbolically how it works. The motor’s two connections can each be switched to the positive or negative pole. In this way, polarity reversal is also possible, depending on which line is connected to positive while the other is connected to negative.

Fig. 9.1.3a: H-bridge

If switches 1 and 4 are closed, the motor runs in one direction. On the other hand, if we close 2 and 3, we get the reverse running direction. If switches 1 and 3 or 2 and 4 are closed, both leads of the motor are connected to positive or both to negative and the motor is off. Under no circumstances should switches 1 and 2 be closed at the same time, or 3 and 4 at the same time, as this would cause a short circuit. Of course, you don’t build an H-bridge using mechanical switches like this, although you could do it with relays. (Switches 1 and 2 could be realized using a single relay with a toggle switch, as could 3 and 4.) Instead, however, you take special ICs that use transistors internally for switching. Such ICs are usually not controlled with four single signals for the four transistors, but only with one signal for the left side and another for the right side. This makes things easier and ensures that both transistors on one side never conduct at the same time, as this would cause a short circuit. Depending on whether the input signal is HIGH or LOW, only the upper or the lower transistor conducts (never both at the same time) and the corresponding motor line is connected to plus or minus.

The L9110S A very cheap H-bridge for max. 12 V and 750 mA is the L9110S. Directly from China, there are small boards for less than one euro that contain two of these H-bridges, and which can control two motors in both directions.

Fig 9.1.3c: Similar version of the board

Fig 9.1.3b: 2 x L9110S

You can also connect the two channels together by tying the corresponding lines of the two H-bridges together. This way you can control only one motor, but at up to 1.5 A. If only one motor is used, I generally recommend using both H-bridges anyway, because if such a motor runs hard, or even at startup, the current can be unexpectedly high. If one is not careful with the current, the L9110S quickly becomes a fuse and simply burns out. 165

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 162

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

The L298N If you need more current or a higher voltage, there are also stronger ICs. For 1 to 2 euro you can get bigger boards from China that use the L298N. This IC already has two H-bridges to control two motors using only one IC. Here, you can also tie the two H-bridges together if necessary. The L298N boards even have a small heat sink and can switch up to 2 A (connected together, max. 4 A) at up to 35 V motor voltage.

Fig. 9.1.3d: L298N board

Fig 9.1.3e: Connections to the L298N board

The picture on the left shows the board’s connections. For each of the 4 outputs there is the respective input pin, whose signal determines whether the output is HIGH or LOW. Next to these 4 input pins, there is another pin on the left and one on the right – ENA and ENB – for the enable signals. ENA must be HIGH to activate outputs 1 and 2, and ENB activates 3 and 4 accordingly.

Behind each of ENA and ENB, there’s a 5-volt pin, so ENA and ENB can also be activated (as shown on the picture) with a jumper plugged in. Thus, we can use either only the 4 input pins IN1 to IN4 with a 4-pin header, and leave the two enable lines always activated by using jumpers, or we remove the jumpers and use a 6-pin header to control all of the pins. The third jumper, labeled “Supply” here, connects the 12-volt input to a voltage regulator, so that the board generates its own 5-volt supply. At the same time, the 12 volts is also the power supply for the outputs (i.e. for the connected motors), and this voltage is allowed to be much higher – up to 35 volts. Only, the voltage regulator does not like more than 12 volts, which means: If our supply voltage for the motors is higher than 12 volts, we have to take out the Supply jumper, and supply the board with 5 volts via the Arduino’s VCC pin. We can then apply a higher voltage, up to 35 volts, to the +12V input. If you want to supply the motor with a lower voltage (7.5 to 12 volts), you can leave the Supply jumper plugged in. But then the +5V connector is only 166

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 163

2022-07-27 20:20

Chapter 9 • Controlling motors

connected to the Arduino’s VCC, in which case the Arduino has to have power supplied to it, i.e. if the Arduino does not have its own power supply. Usually we use Inputs and Outputs 1 and 2 for one motor, and then we can control another motor at 3 and 4. But, we can also connect Inputs 1 and 2 to each other, as well as Outputs 1 and 2. We do the same with 3 and 4. This way we can control one motor, but at double the maximum current. One line of the motor is then connected to Outputs 1 and 2, the other to 3 and 4. For this, however, the corresponding inputs must also be connected to each other.

Control Construction and control with such an H-Bridge board is very simple, in principle. We need two outputs from the Arduino for the two inputs of the H-Bridge. The motor is connected to the two output pins. (If there is a second H-Bridge free on the board, we can add it by simply connecting the corresponding input and output lines to the first bridge). Then, the H-bridge still needs the operating voltage for the motor, and possibly the 5-volt VCC supply (dashed). Fig. 9.1.3e: Control

In the Arduino sketch, we put LOW levels on both outputs when we want the motor to be off. Depending on which line, we then apply a HIGH signal to (a or b), the motor will run in one direction or the other. But we can also apply a HIGH signal to both outputs to switch off the motor. Then we have to switch one or the other line to LOW to make the motor run in one direction or the other.

9.1.4 Full control using H-bridge and PWM Now we can combine both types of control (H-bridge and PWM). This way, we get a control that is adjustable in both directions, seemingly from -100%, through 0, to +100%. Here again we have a small sketch, with which we can control a DC motor by means of a potentiometer or an analog joystick, in both directions. The sketch here uses the min() function for the first time, which I will explain briefly in advance. 167

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 164

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Syntax: min() and max() functions a = min(a, 255); The min() function returns the smaller of two specified values. In this example, variable “a” is limited to 255. If “a” is already smaller than 255, the function returns the value of a. If a is larger, 255 is returned, as the smaller value. a = max(a, 0); The max() function always returns the larger of two values. In this example, “a” has a lower limit: negative values of “a” return 0.

Sketch: Full motor control

9_1_4.ino

#define motor_pin_a 10 // signal for one of the motor lines (must be PWM-capable) #define motor_pin_b 11 // signal for the other motor line (must be PWM-capable) #define pot_pin A0 // signal from potentiometer int power = 0; // actual motor power (from -255 to +255) byte threshold = 10; // threshold from which it will be switched on First, the pins to be used are defined – two PWM-capable outputs for the motor signals and (if you want to use it that way) an analog pin for the potentiometer. Then come two variables. With “power,” we specify the actual motor speed, which goes from -255 to +255. “threshold” specifies the minimum value, above which the motor should be controlled. Otherwise it would not be possible to switch off the motor completely using the potentiometer. You would almost always have a small deviation from 0 (e.g. -2). The motor would stand still, but would consume a small amount of power. void setup() { // Unusually, there's nothing to do here } void loop() { power = (analogRead(pot_pin) >> 1) - 256; // power according to the pot position if (power < threshold && power > -threshold) // if value is near 0 { power = 0; // switch off completely }

168

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 165

2022-07-27 20:20

Chapter 9 • Controlling motors

There's nothing to do here in setup(). In loop(), the “power” value (i.e. the current speed) is defined first. For this, the analog value is measured at the potentiometer pin and halved (by bit-shifting right by one digit). The range from 0 to 1023 becomes a range from 0 to 511. 256 is then subtracted from this. Then we have a range from 256 to +255. Values that are close to 0 (actually, less than “threshold” away from 0) are then set to 0, so that the motor is switched off completely. Instead of getting the “power” value from the potentiometer setting using analogRead(), you can of course replace the first line of the loop with your own program sections that generate the value and thus control the motor. If the value is ever above 255 or below -255, the control will later limit it to this range. if (power >= 0) // at standstill or forward { analogWrite(motor_pin_a, min(power, 255)); // set signal A to 0 to 255 analogWrite(motor_pin_b, 0); // set signal B to 0 } else // backward { analogWrite(motor_pin_b, min(-power, 255)); // set signal B to 0 to 255 analogWrite(motor_pin_a, 0); // set signal A to 0 } } Now the outputs are clocked by PWM based on the “power” value. If “power” is positive or 0, Line A gets the PWM value and Line B is switched to LOW. If “power” is negative, Line B gets the PWM signal (as positive value “-power,”) and Line A is switched to LOW. If “power” is 0, both lines get 0 as PWM value and thus a LOW level. The min() function limits the PWM value to a maximum of 255 in each case.

This is how the corresponding schematic looks when we control the motor using a potentiometer. Depending on the power required, we can use either the L9110S or the L298N board as an H-bridge. The 5-volt connection is also dotted here. After all, it is only needed with the L298N, and only if the Arduino must supply 5 V to the H-bridge, or vice versa. If both have their own supply, it is omitted.

Fig. 9.1.4: Full motor control using a potentiometer

169

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 166

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

9.2 Stepper motors

Fig. 9.2: Stepper motors of various designs and sizes

Stepper motors have the special ability to specify every position exactly and to find it again just as precisely at any time (even after thousands of revolutions). The reason lies in its completely different operation mode. Whereas a DC motor simply starts running as soon as you apply voltage, the stepper motor only ever takes a small step to the next precisely-defined position. In order to jump to the next position (or back to the previous one), the motor needs a signal corresponding to the respective position each time. So, you can let the motor run many revolutions with thousands of steps, and then give it just as many impulses in the other direction, and it ends up exactly at the starting point again.

9.2.1 How it works Simplified, you can imagine a stepper motor as shown in the picture on the right. Two coils arranged at right angles act on the rotor, which is a magnet.

Fig. 9.2.1a: Stepper motor

170

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 167

2022-07-27 20:20

Chapter 9 • Controlling motors

The following image shows how such a stepper motor is controlled. Eight single steps result in one revolution of the rotor.

Fig. 9.2.1b: Controlling an 8-position stepper motor In the first step, a voltage is applied to the horizontal coil. The current generates a magnetic field which attracts the opposite pole of the rotor. If, in the second step, a voltage is also applied to the vertical coil, the pole of the rotor is attracted by both coils and it turns an eighth of a turn. In the third step, the voltage is removed from the horizontal coil. Now only the vertical coil is active and the rotor turns again by an eighth of a turn. In order for it to rotate further, a voltage with reversed polarity must now be applied to the horizontal coil in step 4, and so on. After every 8 steps, the motor has made exactly one revolution. The ninth step then corresponds with the first again. To reverse the running direction, the step sequence only has to run in reverse. For example, if the motor is currently in position 7, then position 6 follows, not 8.

Bipolar and unipolar versions A disadvantage of this control mechanism (with two coils) is that we have to control the coils in a bipolar fashion, meaning in both directions. Therefore, we need two complete H-bridges, as described in section 9.1.3, to control the motor. But, there’s another way!

171

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 168

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Fig. 9.2.1c: Stepper motors with 4 coils Here we now have 4 coils to control the 8 positions. Each coil must be controlled only in one direction (i.e. unipolar). This way, we can, for example, connect the positive poles of all 4 coils and connect them to the supply voltage. We can then use four transistors to connect the individual negative poles to ground. This is a bit easier than using two H-bridges.

Full- and half-step operation What I have described in the previous sections is the so-called half-step operation, which is commonly used and also recommended. For the sake of completeness, I would also like to briefly introduce the simplified full-step operation.

Fig. 9.2.1d: Stepper motor with simplified full-step control Here, only the vertical or the horizontal coil is activated. The intermediate steps, where both coils are activated at the same time, are simply skipped. Thus, one has only 4 steps (instead of 8) per revolution. 172

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 169

2022-07-27 20:20

Chapter 9 • Controlling motors

Conversely, the number of steps can also be increased. With special procedures, the vertical and horizontal coil is then controlled differently, so that additional intermediate steps result. You get e.g. 16, 32, or even more steps per revolution. More about this later, in sections 9.2.3 and 9.2.4.

Actual stepper motors In reality, stepper motors are usually constructed a little differently – unlike in Fig. 9.2.1d, no distinction is made between coils on one side and on the opposite side. In principle, both are the same coil, acting with one magnetic pole on one side of the rotor, and with the other pole on the opposite side of the rotor. In the unipolar version with 4 coils, the two coils simply have two windings, or one winding with a center tap:

Fig. 9.2.1e Bipolar version with 4 connections, and unipolar version with 5 The unipolar version on the right has the center taps already connected. This line is usually used as a common positive pole, while the other 4 lines can each be connected to ground using a transistor. Usually, these 4 lines are then also labeled in the order in which they are controlled, i.e. first A, then A+B, B, B+C, C, C+D, D, D+A, and then again only A, and so on. If the center taps are not interconnected, the motor has 6 leads. It can then be used either in a bipolar fashion, by not using the center taps at all, or in a unipolar one, by connecting them and using them as a common positive pole. With high-quality stepper motors that only take very small steps – and most of them do – there is another difference from the schematic. The rotor has not just 2 magnetic poles around it, but many more. Likewise, the coils with their two poles also act alternately on several places on the rotor. So the motor does much smaller steps and completes a revolution after not only 8, but, for example after 8  8, or 64 steps. 173

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 170

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Pros and cons of each version Bipolar stepper motors (2 coils, 4 connections) are usually somewhat better and more efficient, since they always use the entire coil, whereas unipolar operation always uses only half the coil (from the center tap). High-quality stepper motors, for example in 3D printers, are therefore almost always bipolar. For simple applications, however, there are also very inexpensive unipolar motors, even with internal gears. This gives us a resolution of thousands of steps per revolution.

9.2.2 The 28BYJ-48 The 28BYJ-48 is a unipolar stepper motor with integrated gearbox, which can be used for many purposes. It is available in 5- and 12-volt versions, and you can get it very cheaply from China, at AliExpress, for example, for just under 2 euro. Many offerings even include a matching ULN2003 driver board, so that you can connect an Arduino directly.

Fig. 9.2.2b: With driver

Fig. 9.2.2a: Stepper 28BYJ-48 The motor itself makes 32 steps per revolution, or 64 in half-step mode, and according to the manufacturer, the step size is reduced by another factor of 64 by the internal gear. But, the actual ratio is 25,792 / 405, so only about 63.68395. But, I have also bought such motors where the ratio was 513 / 8, or 64.125, and supposedly there is even a version that actually has a factor of exactly 64. But, that’s the way it is with some bargains: If you buy the same thing 5 times, you get 6 versions.

In half-step mode, we therefore have 64  25,792 / 405 = 4075.7728395 steps in total per revolution, i.e. no integer value at all. In the other versions, however, there are exactly 4104 or 4096 steps. But this doesn’t have to concern us, because, for most applications, these small deviations don’t matter at all. Only someone who wants to build a clock with it had better test which version was received. This can be done, for

174

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 171

2022-07-27 20:20

Chapter 9 • Controlling motors

example, by running the motor many times exactly one round in the same direction (each time with a short pause). If we do the math using the correct numbers, the motor will still stop at exactly the same place even after hundreds of laps. Sometimes, the gearbox’s relatively large play can be annoying. You can always move the axis (at the same step position) a little bit back and forth – there’s always a wiggle in the extent of a few steps. The high gear ratio has other advantages and disadvantages. The relatively weak motor still has a lot of power. Every angle of rotation can be controlled very precisely (if you disregard the play), but fast revolutions are, unfortunately, not possible. For one revolution, the motor usually needs several seconds.

Control using a ULN2003 driver board This (often supplied) driver board is quite suitable for control. It uses the ULN2003, which we already know from section 7.2.5. With the 5 V version of the motor, the 4 coils each have a resistance of about 22 ohms. The 12 V version has a resistance of about 108 ohms per coil. So, the maximum possible current for the 5 V version is about 200 mA, and, for the 12 V version, about 100 mA. The load is thus far within the acceptable range for both versions, and the IC also has the necessary freewheeling diodes already integrated. In addition, the 4 LEDs on the driver board always show the current switching state.

9.2.2c: ULN2003 board

175

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 172

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Control using 4 transistors Alternatively, we can of course switch the 4 coils using 4 transistors. The BC337 is more than adequate for this:

Fig. 9.2.2d: The 28BYJ-48 controlled using 4 bipolar transistors Here, we should also install the 4 freewheeling diodes, which are already in the ULN2003. Instead of bipolar transistors, you could also use 4 MOSFETs of type NTD4906N or IRLR8726PbF, as described in section 7.2.4 on page 102. The motor lines are controlled in the order in which they are connected to the connector. So, first (next to the red common positive line) orange, then yellow, violet (or pink), and then blue, or in reverse order if the motor is to run in backwards. V2 is the voltage that supplies the motor. Depending on the version, this can be 5 V or 12 V. Hence the dotted line to VCC. But, we should not use VCC from the Arduino to power the motor if the voltage comes from the Pro Mini’s voltage regulator, because it might be overloaded. We can instead use another 5-volt supply (V2) to drive the motor and the Arduino.

176

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 173

2022-07-27 20:20

Chapter 9 • Controlling motors

Tip: Stepper motor under battery operation The 5-volt version of the 28BYJ-48 stepper motor is also perfectly suited for battery-powered devices with lithium-ion batteries. The motor still works fine with 3 to 3.5 volts, if the single step pulses are long enough, i.e. if you don't let the motor run too fast. For switching, however, I don't recommend the ULN2003, but instead 4 transistors (as described in the previous section), because with the ULN2003 IC (due to the internal Darlington circuit) there always remains a small residual voltage of about 1 V to ground, so that the motor coils get even less voltage. With simple transistors, the voltage loss is less. Likewise with the special MOSFETs, which still switch very well with 3 volts at the low current of this motor.

For controlling the 28BYJ-48 stepper motor, here’s another sketch:

Sketch: 28BYJ-48 stepper motor control #define #define #define #define

9_2_2.ino

pin_a 2 pin_b 3 pin_c 4 pin_d 5

First, the 4 motor pins are defined. I recommend using 4 pins that are next to each other, so that you can plug a cable with 4-pin female connector on both sides directly from the Pro Mini board to the ULN2003 driver board. long motor_position = 0; // actual position long target_position = 0; // new position byte cycle_position = 0; // position in motor cycle (0 to 7) unsigned int step_duration = 1500; // step duration in microseconds unsigned int start_duration = 6000; // initial step duration in microseconds unsigned int elapsed_time; // elapsed time in milliseconds from actual step unsigned int last_time; // previous time unsigned int real_duration = 0; // real actual step duration byte motor_delay = 5; // total cycles until motor is switched off byte motor_on = 0; // remaining cycles until motor is switched off The motor speed is determined by the “duration” variables. In addition to the actual “step_” value, there is also the “start_” value, with which we create a short (quick) acceleration phase when starting the motor. This allows us to achieve much higher speeds, which the motor would not be able to achieve if it were started cold. The other variables are self-explanatory.

177

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 174

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

void setup() { pinMode(pin_a, OUTPUT); // set motor pins to output digitalWrite(pin_a, LOW); // and turn them off pinMode(pin_b, OUTPUT); digitalWrite(pin_b, LOW); pinMode(pin_c, OUTPUT); digitalWrite(pin_c, LOW); pinMode(pin_d, OUTPUT); digitalWrite(pin_d, LOW); real_duration = start_duration; last_time = millis(); } setup() is as normal. The motor pins are set as outputs and turned off. Then, the initial step duration for acceleration and the time are set. void loop() { elapsed_time = micros() - last_time; if (elapsed_time >= real_duration) // if step duration is reached { last_time += real_duration; In loop(), the elapsed time (since the last step) is first determined and we check whether the step duration has been reached. Only then is last_time updated and further motor control executed. It is notable that all the time variables are in unsigned int format, although micros() returns a long value. Nevertheless, we always get the correct value, even if last_time overflows every now and then and even if the system time overflows. After all, elapsed_time cannot be less than zero. Likewise, an unsigned variable cannot be negative. So, the value is always correct – even if the variable overflows. And, we’re only dealing with short times of a few thousand microseconds, so the values are never too large. if (target_position == motor_position) // if target is reached { if (motor_on) { motor_on--; // reduce remaining cycles until deactivation if (!motor_on) { digitalWrite(pin_a, LOW); // switch off all pins digitalWrite(pin_b, LOW); digitalWrite(pin_c, LOW); digitalWrite(pin_d, LOW);

178

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 175

2022-07-27 20:20

Chapter 9 • Controlling motors

real_duration = start_duration; }

}

} If the current position matches the target position, the target has been reached. If the motor is still on at that point, we count down from 5 (value of motor_delay). After the 5 passes during which the motor is stationary, all 4 coils are switched off. This small switch-off delay ensures that the motor actually stops in the desired position. Now the step duration is set to the initial value. else // if target is not reached { if (real_duration > step_duration) // if acceleration phase { real_duration /= 1 + (float(real_duration) / 50000); // accelerate constantly } if (real_duration < step_duration) // if step duration would fall below minimum { real_duration = step_duration; // minimum duration (maximum speed) } If, on the other hand, the target has not yet been reached, we check whether the real step duration is longer than the regular (fastest) step duration. Then, the motor is still in the acceleration phase and the real step duration is slightly shortened. This odd formula results from the fact that the real duration also defines the timing of this correction. If the calculation clock were constant, we could divide the time by a fixed factor (e.g. 1.02) to accelerate evenly. Here, strictly speaking, we should even have to work with power calculations, but this formula gives a very good approximation. Here, the number 50,000 determines how fast the acceleration is. A larger value (e.g. 500,000) would slow down the acceleration.

179

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 176

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

if (!motor_on) // if motor is still off { motor_on = motor_delay; // switch on only (do not make a step yet) } else // if motor was already on { if (target_position > motor_position) // if target direction is forward { motor_position++; cycle_position++; } else // if target direction is backwards { motor_position--; cycle_position--; } cycle_position &= 7; // only the lowest 3 bits (0 to 7) } Now (since the target has not yet been reached) a distinction is made as to whether the motor is already on. If this is not the case – i.e. if it has only just been started, motor_on is set to motor_delay. This value serves later as a switch-off delay. But, no movement is executed yet, in order to re-engage in exactly the old position. Only at the next step (if the motor was already switched on) the position variables are counted up or down. The “cycle_” variable is truncated to the last three bits at the end. It only indicates the motor cycle and only counts in the range 0 to 7, while motor_position may also be a very large (or even negative) number and indicates the total position. if (cycle_position == 0) { digitalWrite(pin_a, HIGH); digitalWrite(pin_d, LOW); digitalWrite(pin_b, LOW); } else if (cycle_position == 1) { digitalWrite(pin_a, HIGH); digitalWrite(pin_b, HIGH); } else if (cycle_position == 2) { digitalWrite(pin_b, HIGH); digitalWrite(pin_a, LOW); digitalWrite(pin_c, LOW); } 180

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 177

2022-07-27 20:20

Chapter 9 • Controlling motors

else if (cycle_position == 3) { digitalWrite(pin_b, HIGH); digitalWrite(pin_c, HIGH); } else if (cycle_position == 4) { digitalWrite(pin_c, HIGH); digitalWrite(pin_b, LOW); digitalWrite(pin_d, LOW); } else if (cycle_position == 5) { digitalWrite(pin_c, HIGH); digitalWrite(pin_d, HIGH); } else if (cycle_position == 6) { digitalWrite(pin_d, HIGH); digitalWrite(pin_c, LOW); digitalWrite(pin_a, LOW); } else if (cycle_position == 7) { digitalWrite(pin_d, HIGH); digitalWrite(pin_a, HIGH); } } } Now the corresponding coils are switched on according to the current cycle_position. Two coils should now be on and none should be off, because no matter in which direction the motor runs, we’ve only had one of the two coils activated. If only one coil is now activated, the two neighboring coils must be inactive, because, depending on the running direction one of them was previously active.

181

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 178

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

// Put your own program sections here. With target_position you set new targets. // Example: In this way the motor runs alternately back and forth with 5 s pause. if (!motor_on) // only if the target is reached and the motor is already off { delay(5000); // wait 1 seconds if (target_position > 0) { target_position -= 4104; // approx. one turn backwards } else { target_position += 4104; // approx. one turn forward } } } This section is no longer part of the actual motor control. Here, we place our main program, which transfers the target values to the controller. In the given example, the motor simply runs one round back and forth. But, be careful: We may only use delay() if motor_on is 0 or false, but never while the motor is running, because that would stop it. Conversely, the actual motor control does not use a delay, so the program continues to run while the motor is running and other parts of the program can still be executed.

Usage We can use this program for any 28BYJ-48 stepper motor control purposes. In the lower part, we write our own program, which controls the motor. We can specify new target positions at any time using the target_position variable. To make sure that the motor is not running anymore, i.e. the previous target has been reached, we should use the condition “if (!motor_on)”. If the running direction is the same, we can also specify a new target during operation. If, on the other hand, we want to change the running direction while the motor is moving, we should first execute “target_position = motor_position;”, i.e. set the current position as the target so that the motor stops, and only specify the new target when motor_on is 0. This way, the motor does not change direction abruptly, but stops, and accelerates again.

182

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 179

2022-07-27 20:20

Chapter 9 • Controlling motors

We can also specify a new value for motor_position at any time in the program sequence in order to calibrate the position. With “motor_position = 0;” we define e.g. the current position as zero point. With variable step_duration, we can change the speed. The shorter the steps are, the faster the motor runs. Where the limit is, you just have to test, because it depends on several factors from operating voltage to mechanical load. To be on the safe side, I recommend using only two-thirds of the maximum possible speed, or 1.5 the step time. If you have to control two or three stepper motors, you can duplicate the main program segments, with similar names for all variables, e.g. with x_motor_position, y_motor_position, z_motor_position, and so on. But it’s also necessary to duplicate all time variables, as well as the “if” comparison for whether the corresponding step duration is reached. In principle, we have to loop the entire motor control two or three times (for the respective motor) in succession.

9.2.3 Control using the A4988 The A4988 is a very cheap, nevertheless high-quality chip for the exact control of bipolar stepper motors, i.e. those which have only 2 coils and 4 leads. The current for the coils (and thus the force of the motor) can also be precisely adjusted via a potentiometer. In addition, this part can do microstepping, a method of controlling not only in full or half steps, but optionally in quarter-, eighth- or sixteenth-steps. In this fig. 9.2.3a: A4988 controller process, the two coils are not only switched on and off, but also receive different amounts of current, step -by-step, resulting in the corresponding intermediate steps. Many 3D printers, for example, are controlled using this IC. The A4988 usually comes a small board with everything you need to control it. The pins are commonly labeled on the underside.

183

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 180

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

Pinout On the left here are the input pins that we can control with output signals from the Arduino. DIRECTION: A HIGH or LOW signal is applied here, which determines in which direction the motor runs, or, more precisely, in which direction the next step takes place when a signal is applied to the STEP pin. STEP: With each change from LOW to HIGH at this input, the next step, or microstep, is carried out.

Fig. 9.2.3b: Pin layout

SLEEP: This input must be set HIGH at least 1 millisecond before any motor movement. At LOW level, the motor is switched off.

RESET: This pin must also be HIGH during operation. A LOW signal not only turns off the motor, but also resets the internal position. We can connect this pin to the Arduino’s reset pin. MS1, MS2, MS3: The signals at these three MS1 inputs determine the motor’s step resolution. L In addition to full- and half- step operation, you can also select quarter-, eighth- and H sixteenth- steps. If there’s no reason not to, I L recommend using the finest resolution, i.e. to H set all three lines to HIGH. Usually, we always work with the same resolution. Then, we don't H have to connect these three lines to Arduino outputs, but can connect all three to HIGH, i.e. VCC.

MS2

MS3

Resolution

L

L

full-step

L

L

half-step

H

L

quarter-step

H

L

eighth-step

H

H

1/16-step

ENABLE: This line must be LOW to control the motor. It is best to use this line to switch the motor off between runs using a HIGH signal, while RESET and SLEEP always remain high. GND: Top-right in Figure 9.2.3b. This is the ground pin for voltage VDD. VDD: This is the voltage corresponding to the logic levels at the input. It is connected to VCC from the Arduino. VDD may be in the range of 3.0 to 5.5 volts, so you may also use e.g. a 3.3 V Pro Mini board a LilyPad. 1A & 1B: These are the output pins for the first coil of the motor. 2A & 2B: These are the output pins for the motor’s second coil. GND: This is for the ground for the motor voltage. It is best to connect the respective ground lead of the two voltages (VDD and VMOT) to the associated ground pin next to the voltage pin, but still connect the two ground pins to each other as well.

184

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 181

2022-07-27 20:20

Chapter 9 • Controlling motors

VMOT: The voltage for the motor (8 to 35 V) is applied to the last pin (bottom-right in Fig. 9.3.2b). 12 or 24 V is preferable.

Adjusting the current Before we can use the motor control, we have to adjust the current. To do this, we first need the value of the two shunts, which are labeled S1 and S2 here. The value printed on the resistors, R100, means 0.1 ohms, because R counts as the decimal point. Don’t just count on the 0.1-ohm value, but check it, and calculate using the correct value, because there could be other versions of the board with different resistances.

9.2.3c: A4988 board adjustment

We then have to set a reference voltage at the potentiometer, which is applied to the sliding contact of the potentiometer itself. The well-known formula R = U / I or U = I  R is applied, but, due to the internal electronics, multiplied by a factor 8. The voltage to be set is thus: U=8IR R is the value of one of the two identical resistors. I is the current we want to adjust. The motor does not have to be connected yet, because no motor current flows during the adjustment. We only set a voltage, which will be used to limit the current later. The A4988 can handle a maximum of 2 A, so we must not set the current higher. Rather stick to just 1 A, or 1.5 A, which should be good enough for most applications. For 1 A with shunt resistors of 0.1 ohms each, this means: U = 8  1  0.1 = 0.8 V. Now we need a multimeter, preferably set to the 2-volt range. The negative lead goes to the VDD ground on the driver board (or on the Arduino). The positive test lead goes to the (very small) screwdriver that we use to adjust the potentiometer. Then we turn it until exactly 0.8 V is displayed, or, for 1.5 A, correspondingly 1.2 V. For current settings above 1 A, however, a miniature heat sink should be mounted on the A4988 chip. Many offerings come with these, usually with double-sided adhesive tape. Even better is gluing it on using a drop of heat-conductive glue. But, be careful: The potentiometer must remain free. If several stepper motors and controllers are required for an application, some of the input lines of all of the controllers tied together. Only the signals DIRECTION, STEP, and ENABLE are required separately for each motor. 185

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 182

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

9.2.4 Control using the DRV8825 The DRV8825 is very similar to the A4988. This chip for controlling a bipolar stepper motor is also usually offered on a small board. It can deliver a similar amount of current to the A4988 (2.5 A peak or 1.75 A RMS) and work with a motor voltage of 8.2 to 45 volts. However, experience has shown that it is better to use a motor voltage of only 12 volts with this board. Otherwise, the chip has to be switched to “fast decay,” an operating mode that the board does not support at all, unfortunately. Fig. 9.2.4a: DRV8825 board

Pinout The pinout is almost the same as on the A4988 board. Again, the input pins are on the left, and the power supply and output pins are on the right. DIR: The signal at this input determines the direction of travel, i.e. in which direction the next step goes when a pulse is sent to the STP pin. STP: With each change from LOW to HIGH at this input, the next step or microstep is executed.

Fig. 9.2.4b: Pin layout

SLP: This input must be set HIGH during operation. At LOW level, the motor (as well as parts of the internal electronics) is switched off.

RST: This pin must also be HIGH during operation. A LOW signal turns off the motor and resets the internal position. M0, M1, M2: The signals at these three inputs determine the step resolution of the motor. In addition to full- and half- step operation, you can also select quarter-, eighth-, sixteenth-, and even thirty-second-step operation on this controller. If there’s no reason not to, I recommend using the highest resolution, that is, setting all three lines to HIGH. That way, we don’t need an Arduino output here either, but can connect these three lines permanently to VCC.

M0

M1

M2

Resolution

L

L

L

full-step

H

L

L

half-step

L

H

L

quarter-step

H

H

L

eighth-step

L

L

H

1/16-step

H

H

H

1/32-step

186

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 183

2022-07-27 20:20

Chapter 9 • Controlling motors

EN: This line must be LOW for the motor to get power. It is best to use this line to switch off the motor between runs with a HIGH signal here, while RESET and SLEEP stay high. GND: In the upper-right corner of Figure 9.2.4b is the ground pin for the input signals, which we connect to the Arduino ground. FLT: The VCC voltage from the Arduino is not applied to this output (as is the case with the A4988). On the DRV8825 board, this is an output that is normally HIGH, but goes LOW in the event of an error (if the temperature or current is too high). 1A, 1B: These are the output pins for the first coil of the motor. 2A, 2B: The second coil of the motor is connected here. GND: This is the motor voltage’s ground. It is best to connect the ground from the Arduino to the other ground pin, but tie the two ground pins together anyway. VMOT: The voltage for the motor is applied to the last pin (bottom-right in Figure 9.2.4b) (8.2 to 45 V). However, it is preferable to use only 12 V.

Adjusting the current Before we can use the motor control, we have to set the current on this version as well. Here, the two identical resistors for current measurement are right next to the potentiometer. Printed values R100 mean 0.1 ohms each, because R stands for the decimal point. But, there can also be different versions of the board. Therefore, we should always check first and calculate using the correct value. The reference voltage, which we have to measure and set, is also set directly using the potentiometer, and here we also have to include a calculation factor, not 8 this time (as with the A4988), but rather 5. The voltage we have to set is thus: U=5IR R is again the value of one of the two resistors. I is the current we want to set. Here, too, no motor current flows during adjustment, because we are only setting a voltage that will later be used to limit the current. Example: If we want to set the current to 1.5 A, we calculate 5  1.5  0.1 = 0.75 V. Now we need a multimeter, preferably set to the 2-volt range. The negative test lead goes to the ground pin, which is connected to the Arduino ground. The positive lead goes to the (very small) screwdriver, which we use to adjust the potentiometer. We now turn it until exactly 0.75 V is displayed. Again, a mini heat sink should be glued to the DRV8825 chip if the current is to be above 1 A. Often, such mini heat sinks are supplied. 187

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 184

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

9.2.5 Version A4988 vs. DRV8825 The main difference between these two controllers is the number of maximum possible microsteps. While the A4988 can go down to sixteenths of a steps, the DRV8825 also allows thirty-second steps, although this does not necessarily mean higher accuracy. If you don’t need the highest resolution of 32 microsteps, it’s better to use the A4988 board. It can only do sixteenth microsteps, but is generally considered to be more precise, and the step size is more uniform.

9.3 Brushless motors In many other motors, the coils rotate and are supplied with current via sliding contacts. For this purpose, carbon rods (so-called carbon brushes) are usually used, which have to be replaced after a few years in many conventional motors. The brushless motor works the other way round. The coils are fixed and the magnet rotates. This has the advantage that no sliding contacts are needed. Brushless motors are therefore more durable, and are usually more efficient. Equipped with high-quality magnets, even small motors can perform amazingly well. Drones, for example, almost exclusively use such motors, as well as e-bikes, e-scooters and even electric cars.

Fig. 9.3: Three different brushless motors One disadvantage is that brushless motors cannot simply be supplied with direct current, as this would cause them (like a stepper motor) to simply remain in their current position. Instead, the three coils need a kind of three-phase current, whose frequency and phase position must be synchronous with the motor rotation. 188

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 185

2022-07-27 20:20

Chapter 9 • Controlling motors

9.3.1 Control using ESC This difficult task is taken over by a socalled ESC (electronic speed control), a module with a lot of electronics. Such ESCs contain three half-H-bridges (i.e. one H-bridge for three lines), with which up to 10, 20, 30, or 40 A can be switched, plus a dedicated microcontroller (a kind of Arduino) on which an internal motor control program runs. This all sounds very expensive, but you can get one straight from China for as little as 4 euro. You can also search specifically for “SimonK.” This name refers to special firmware, a control program that works with a high switching frequency, reacts quickly, and is therefore very popular. Fig. 9.3.1a: ESC for up to 30 A with SimonK Firmware

Power supply Such ESCs are mainly used for operation on rechargeable batteries, for example in quadcopters. The permissible operating voltage is therefore often given as the number of lithium-ion batteries connected in series, e.g. as “2 to 3S” or “2 to 4S.” This means either 2 to 3 batteries in series or 2 to 4. When fully charged, such a battery cell has up to 4.2 volts, and when almost empty, 3.5 volts. This results in a permissible voltage range of 7 to 12.6 volts, or up to 16.8 volts with 4 batteries in series. For mains operation, I recommend a 12-volt power supply, because that is always adequately sized, unless you need even more power, in which case a higher voltage may be useful.

The connections ESCs usually have a thick black wire for motor ground, and an equally thick red wire for the positive pole. On the other side are usually three more thick wires connected to the three motor wires. There is no order to follow, but only a very simple rule: If the motor must run backwards simply swap two of the three wires – it doesn’t matter which two.

189

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 186

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

To control the ESC there is a thin wire with three strands, usually red, black (or brown), and yellow (or white). Red and black are plus and minus for a small 5V voltage, which the ESC generates internally. Here, for example, a Pro Mini board could be connected directly to VCC (or RAW). If our Arduino already has its own power supply, we don't connect the red wire at all, but only the black ground wire to the Arduino ground. The yellow (sometimes also white) signal line is connected to one of the board’s outputs.

Control signal ESCs are controlled using regular pulses on the control line. This method has been used for decades for remote-control model cars and aircraft. Servos (e.g. for steering) are also controlled using such a signal. The pulse frequency may be between 50 and 500 Hz. It is best to do 100 pulses per second, or slightly more. The frequency is actually unimportant. Control depends on the duration of the pulses, which should normally be between 1000 and 2000 µs. At 1000 µs, the motor is off. At 2000 µs, it runs at maximum power. In between, we can control it from 0 to 100 percent. The following small example program converts the measured value of a potentiometer into pulses, so that we can use the ESC to control the motor via the potentiometer.

Sketch: ESC-control using potentiometer

9_3_1.ino

#define signal_pin 2 #define pot_pin A0 byte power; // motor power (0 to 255) unsigned int pot_16; // measured value (16 bit) byte n; // count variable void setup() { pinMode(signal_pin, OUTPUT); // set signal pin to output digitalWrite(signal_pin, LOW); } First the constants for the I/O pins used are defined here – an output pin for the ESC signal and an analog input pin from the potentiometer. Then come the variables “power” for the motor power, pot_16 for the analog measurement and a variable for counting. In setup(), only the signal pin is initialized.

190

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 187

2022-07-27 20:20

Chapter 9 • Controlling motors

void loop() { pot_16 = 0; // reset for (n=0; n> 8; // to 8 bit (0-255) digitalWrite(signal_pin, HIGH); // start pulse delayMicroseconds(1000); delayMicroseconds(power 4x , 3 -> 8x int duration[4] = {4500, 7500, 13500, 25500}; // times (µs) depending on oversampling int ac1, ac2, ac3, b1, b2, mb, mc, md, n, temperature; // several variables unsigned int ac4, ac5, ac6, t, next_time; long x1, x2, x3, b3, b5, b6, p, pressure, altitude; unsigned long b4, b7; After including Wire.h for the I²C communication, the 7-bit address of the BMP180 sensor is defined as a constant called “address.” The prefix 0x indicates that the value (77) is specified in hexadecimal notation. Then, the required variables are defined. For “oversampling,” we use the values 0 to 3 to specify whether 1, 2, 4, or 8 measurements are taken at a time, respectively – more measurements increase the accuracy somewhat. The array indicates how long we have to wait for the measurement result for each of the different oversampling settings. The other variables have been separated by commas, because this allows us to define several variables of the same type at the same time. void setup() { Wire.begin(); // prepare I2C transmission Wire.beginTransmission(address); // select device (BMP180) Wire.write(0xAA); // position of the calibration data in the BMP180 chip Wire.endTransmission(); In setup(), the I²C transmission is set up as master with Wire.begin(). Then, the sensor is set to register 0xAA, also specified in hexadecimal notation. Wire.requestFrom(address,22); // load calibration data (22 bytes or 11 int values) ac1 = read_int(); // reads the next two bytes in each line ac2 = read_int(); ac3 = read_int(); ac4 = read_int(); ac5 = read_int(); ac6 = read_int(); b1 = read_int(); b2 = read_int(); mb = read_int(); mc = read_int(); md = read_int(); Serial.begin(38400); // prepare serial transmission 214

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 211

2022-07-27 20:20

Chapter 10 • Sensors

}

Serial.println("Calibration data:"); // serial output Serial.println(ac1); Serial.println(ac2); Serial.println(ac3); Serial.println(ac4); Serial.println(ac5); Serial.println(ac6); Serial.println(b1); Serial.println(b2); Serial.println(mb); Serial.println(mc); Serial.println(md);

Now, 22 bytes are read from the previously specified address (0xAA) and 11 16-bit integer variables are formed from them. The actual reading of 2 bytes at a time is done using the read_int() function, which is located at the end of the sketch. The values are individual calibration data, which the manufacturer of the BMP180 has stored there for us. We need this data later to determine the exact temperature and the exact air pressure from the measured values. For control, this data is then also output to Serial Monitor. void loop() { get_t(); // read temperature value get_p(); // read pressure value calculate(); // calculate temperature and pressure from raw data altitude = 4433000 * (1-pow(((float)pressure/101325),1/5.255)); // height in cm Serial.print("Temp.: "); // display temperature, pressure and altitude Serial.print(((float)temperature/10), 1); Serial.print("°C Value: "); Serial.print(p); Serial.print(" Pressure: "); Serial.print(((float)pressure/100), 2); Serial.print("hPa(mbar) Altitude: "); Serial.print(((float)altitude/100), 2); Serial.println("m"); delay(1000); } In loop() the get_t() and get_p() are called to read the values for temperature and air pressure. Even if only the pressure is needed, the temperature measurement is important, because both values are just raw data, and to calculate the pressure exactly, the temperature value is also necessary. This is done in the next step. The calculate() function determines the exact temperature and pressure, with the help of the 11 calibration variables, and, in the next line, the altitude is calculated. 215

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 212

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

The data is then output serially and can be tracked in Serial Monitor. The temperature, in tenths of a degree, is converted to degrees, and the pressure is converted from Pascal to Hectopascal, which also corresponds to the “millibar” unit. The delay at the end sets the output clock to one second. void get_t() // measure temperature { Wire.beginTransmission(address); // address BMP180 Wire.write(0xF4); // select control register Wire.write(0x2E); // value for temperature measurement Wire.endTransmission(); // complete action delayMicroseconds(4500); // wait for result Wire.beginTransmission(address); // address BMP180 Wire.write(0xF6); // select address for measurement result Wire.endTransmission(); // complete action Wire.requestFrom(address,2); // read measured value (16 bit) t = read_int(); // read 16 bit (2 byte) } Now for the function for reading the raw temperature data. First, the Control register (0xF4) is selected, and the value 0x2E is written to it, which means that we want to measure temperature. Then, a delay of 4.5 ms is applied, because this is how long the temperature measurement takes until the result is available. Then, Register 0xF6 is selected, because the result is written to registers 0xF6 and 0xF7. So, 2 bytes are requested starting from the current address. To read them, the read_int() function is again used. void get_p() // measure pressure { Wire.beginTransmission(address); // address BMP180 Wire.write(0xF4); // select control register Wire.write(0x34 + (oversampling 15; // calculate temperature x2 = ((long)mc > 4; // temperature (in tenths of degrees)

}

b6 = b5 - 4000; x1 = (b2 * ((b6 * b6) >> 12)) >> 11; x2 = (ac2 * b6) >> 11; x3 = x1 + x2; b3 = ((((long)ac1 * 4 + x3) > 2; x1 = (ac3 * b6) >> 13; x2 = (b1 * ((b6 * b6) >> 12)) >> 16; x3 = (x1 + x2 + 2) >> 2; b4 = (ac4 * (unsigned long)(x3 + 32768)) >> 15; b7 = ((unsigned long)p - b3) * (50000 >> oversampling); if (b7 < 0x80000000) pressure = (b7 * 2) / b4; else pressure = (b7 / b4) * 2; x1 = (pressure >> 8)*(pressure >> 8); x1 = (x1 * 3038) >> 16; x2 = (-7357 * pressure) >> 16; pressure += (x1 + x2 + 3791) >> 4; // pressure (in pascal)

This function now calculates the exact temperature in tenths of a degree and the pressure in Pascal from the raw data, “t” (for temperature) and “p” (for pressure), according to the manufacturer’s specifications. The function uses the 11 calibration variables, as well as 8 additional temporary variables (x1 to x3 and b3 to b7). All these calculations (from the data sheet) cannot and need not be understood – no, really!

217

arduino_and_co_DM 2022-07-27 CROPMARKS.pdf 214

2022-07-27 20:20

Arduino & Co – Measure, Control, and Hack

unsigned int read_int() // read two bytes as an integer from the I2C bus { while(!Wire.available()); // wait unsigned int int_register = Wire.read() 128, 1 -> 64, 2 -> 32, 3 -> 16) ADCSRA |= (1