Zumo32U4 library
Zumo32U4ProximitySensors.cpp
1// Copyright Pololu Corporation. For more information, see http://www.pololu.com/
2
4#include <Zumo32U4IRPulses.h>
5#include <Arduino.h>
6#include <FastGPIO.h>
7#include <stdlib.h>
8
9// The Arduino's digitalRead, digitalWrite, and pinMode functions will have
10// unexpected behavior if the pin number argument happens to be greater than
11// NUM_DIGITAL_PINS. We protect users of our library from that.
12static bool digitalReadSafe(uint8_t pin, bool defaultValue = 1)
13{
14 if (pin < NUM_DIGITAL_PINS)
15 {
16 return digitalRead(pin);
17 }
18 else
19 {
20 return defaultValue;
21 }
22}
23
24static void pinModeSafe(uint8_t pin, uint8_t mode)
25{
26 if (pin < NUM_DIGITAL_PINS)
27 {
28 pinMode(pin, mode);
29 }
30}
31
32void Zumo32U4ProximitySensors::clearAll()
33{
34 dataArray = NULL;
35 numSensors = 0;
36
37 lineSensorEmitterPin = SENSOR_NO_PIN;
38
39 levelsArray = NULL;
40 numLevels = 0;
41
42 pulseOnTimeUs = defaultPulseOnTimeUs;
43 pulseOffTimeUs = defaultPulseOffTimeUs;
44 period = defaultPeriod;
45}
46
47void Zumo32U4ProximitySensors::init(uint8_t * pins, uint8_t numSensors,
48 uint8_t lineSensorEmitterPin)
49{
50 this->lineSensorEmitterPin = lineSensorEmitterPin;
51
52 // Allocate memory for the new dataArray. If there is an error, return
53 // before modifying the existing dataArray or numSensors so that we
54 // don't leave the object in an invalid state.
55 const size_t size = numSensors * sizeof(SensorData);
56 void * newArray = realloc(dataArray, size);
57 if (newArray == NULL) { return; }
58
59 // Store the pointer to the new dataArray.
60 this->dataArray = (SensorData *)newArray;
61
62 // Store the number of sensors.
63 this->numSensors = numSensors;
64
65 for (uint8_t i = 0; i < numSensors; i++)
66 {
67 // Store the pin numbers specified by the user.
68 dataArray[i].pin = pins[i];
69 }
70}
71
72
73void Zumo32U4ProximitySensors::setBrightnessLevels(uint16_t * levels, uint8_t numLevels)
74{
75 const size_t size = numLevels * sizeof(uint16_t);
76
77 void * newArray = realloc(levelsArray, size);
78 if (newArray == NULL)
79 {
80 // There was an error allocating memory so just leave the
81 // state of the object the same as it was before.
82 return;
83 }
84
85 memcpy(newArray, levels, size);
86 levelsArray = (uint16_t *)newArray;
87 this->numLevels = numLevels;
88}
89
90void Zumo32U4ProximitySensors::prepareToRead()
91{
92 pullupsOn();
93
95
96 if (levelsArray == NULL)
97 {
98 uint16_t defaultBrightnessLevels[] = { 4, 15, 32, 55, 85, 120 };
99 setBrightnessLevels(defaultBrightnessLevels, 6);
100 }
101}
102
104{
105 // Set all the sensor pins to be pulled-up inputs so that they
106 // are high whenever the sensor outputs are not active.
107 for (uint8_t i = 0; i < numSensors; i++)
108 {
109 pinModeSafe(dataArray[i].pin, INPUT_PULLUP);
110 }
111}
112
113// Turn off the down-facing IR LEDs because the proximity
114// sensors tend to detect the IR coming from them.
116{
117 if (lineSensorEmitterPin < NUM_DIGITAL_PINS)
118 {
119 digitalWrite(lineSensorEmitterPin, LOW);
120 pinMode(lineSensorEmitterPin, OUTPUT);
121 delayMicroseconds(pulseOffTimeUs);
122 }
123}
124
125/* It is not feasible to turn off the pulses before checking the output of
126 * the sensor because an interrupt might fire and cause the sensor check to
127 * happen too late.
128 */
130{
131 prepareToRead();
132
133 for (uint8_t i = 0; i < numSensors; i++)
134 {
135 dataArray[i].withRightLeds = 0;
136 dataArray[i].withLeftLeds = 0;
137 }
138
139 for (uint8_t i = 0; i < numLevels; i++)
140 {
141 uint16_t brightness = levelsArray[i];
142
144 delayMicroseconds(pulseOnTimeUs);
145 for (uint8_t i = 0; i < numSensors; i++)
146 {
147 if (!digitalReadSafe(dataArray[i].pin, 1))
148 {
149 dataArray[i].withLeftLeds++;
150 }
151 }
153 delayMicroseconds(pulseOffTimeUs);
154
156 delayMicroseconds(pulseOnTimeUs);
157 for (uint8_t i = 0; i < numSensors; i++)
158 {
159 if (!digitalReadSafe(dataArray[i].pin, 1))
160 {
161 dataArray[i].withRightLeds++;
162 }
163 }
165 delayMicroseconds(pulseOffTimeUs);
166 }
167}
168
169bool Zumo32U4ProximitySensors::readBasic(uint8_t sensorNumber)
170{
171 if (sensorNumber >= numSensors) { return 0; }
172 return !digitalReadSafe(dataArray[sensorNumber].pin, 1);
173}
174
175uint8_t Zumo32U4ProximitySensors::countsWithLeftLeds(uint8_t sensorNumber) const
176{
177 if (sensorNumber >= numSensors) { return 0; }
178 return dataArray[sensorNumber].withLeftLeds;
179}
180
181uint8_t Zumo32U4ProximitySensors::countsWithRightLeds(uint8_t sensorNumber) const
182{
183 if (sensorNumber >= numSensors) { return 0; }
184 return dataArray[sensorNumber].withRightLeds;
185}
186
187uint8_t Zumo32U4ProximitySensors::findIndexForPin(uint8_t pin) const
188{
189 for (uint8_t i = 0; i < numSensors; i++)
190 {
191 if (dataArray[i].pin == pin)
192 {
193 return i;
194 }
195 }
196
197 // The specified pin is not being used as a sensor, so return 255. This can
198 // be safely passed to countsWithLeftLeds, countsWithRightLeds, or
199 // readBasic, and those functions will return 0.
200 return 255;
201}
static const uint8_t SENSOR_NO_PIN
A constant that can be used in place of a pin number to indicate that no pin should be used.
static void stop()
Stops emitting IR pulses.
static void start(Direction direction, uint16_t brightness, uint16_t period=defaultPeriod)
Starts emitting IR pulses.
void read()
Emits IR pulses and gets readings from the sensors.
static const uint16_t defaultPeriod
The default period for the infrared pulses.
void init(uint8_t *pins, uint8_t numSensors, uint8_t lineSensorEmitterPin=defaultLineSensorEmitterPin)
Configures this object to use a custom set of pins.
uint8_t countsWithRightLeds(uint8_t sensorNumber) const
Returns the number of brightness levels for the right LEDs that activated the specified sensor.
void setBrightnessLevels(uint16_t *levels, uint8_t levelCount)
Sets the sequence of brightness levels used by read().
void lineSensorEmittersOff()
Turns the IR emitters for the line sensors off.
bool readBasic(uint8_t sensorNumber)
Does a quick digital reading of the specified sensor without emitting any IR pulses.
static const uint16_t defaultPulseOffTimeUs
The default time to leave the infrared LEDs off between readings, in microseconds.
static const uint16_t defaultPulseOnTimeUs
The default duration of the bursts of infrared pulses emitted, in microseconds.
uint8_t countsWithLeftLeds(uint8_t sensorNumber) const
Returns the number of brightness levels for the left LEDs that activated the specified sensor.
void pullupsOn()
Sets each sensor pin to an input with pull-up resistors enabled.