nanoI2CSlaveExpander
ARDUINO Nano v3 used as I2C slace digital and analog io expander for ESP8266 and others...
nanoI2CIOExpLib.cpp
Go to the documentation of this file.
1 /**
2  @file nanoI2CIOExpLib.cpp
3  @author J.SORANZO
4  @date 21/03/2019
5  @copyright 2018 CC0
6  @version git versionning
7  @brief implementation file of the class CNanoI2CIOExpander
8 */
9 
10 #include <Arduino.h>
11 #include <Wire.h>
12 #include "nanoI2CIOExpLib.h"
13 
14 #define NANOEXP_ADDRESS 0x58
15 
16 bool CNanoI2CIOExpander::initOk = false;
17 
18 /**
19  @fn void CNanoI2CIOExpander::begin( int add = 0x58 )
20  @brief function that start the I2C protocol with nanoI2CIOExpander
21  @param add the I2C address of the componant...
22  @return nothing
23 
24  The default address of the componant is 0x58
25  Can be fixed from 0x58 to 0x59 with D12D10D11 pin of the Nano
26  The only one adress pin D13 is pulled-down (so no connect value is 0)
27 */
28 void CNanoI2CIOExpander::begin( int add ){
29  Wire.begin();
30  Wire.beginTransmission(NANOEXP_ADDRESS);
31  if ( Wire.endTransmission() ) return;
32  if ( readRegister( REGTEST3 ) != 0x55 ) return;
34  return;
35 
36 }
37 
38 /**
39  @fn void CNanoI2CIOExpander::pinMode( int output, int mode)
40  @brief A method to set the pinMode but...
41  @param output from 0 to 10
42  @param mode INPUT, OUTPUT or INPUT_PULLUP
43  @return nothing
44 
45  @warning input number from 0 to 10 corresponding to D2 to D12 on the nano
46 */
47 void CNanoI2CIOExpander::pinMode( int output, int mode){
48  if ( output > 12 ) return;
49  int regAdd;
50  int regPuAdd;
51  int bitNumber;
52  bitNumber = output<=7?output:output-8;
53  regPuAdd = output<=7?PULLUP:PULLUP2;
54  regAdd = output<=7?DDR:DDR2;
55  int DDRVal;
56  int pullupVal;
57  DDRVal = readRegister( regAdd );
58  pullupVal = readRegister( regPuAdd );
59  if ( mode == INPUT ) {
60  bitClear( DDRVal, bitNumber );
61  bitClear( pullupVal, bitNumber );
62  } else if (mode == OUTPUT) bitSet( DDRVal, bitNumber );
63  else if (mode == INPUT_PULLUP ){
64  bitClear( DDRVal, bitNumber );
65  bitSet( pullupVal, bitNumber );
66  }
67  writeRegister( regAdd, DDRVal );
68  writeRegister( regPuAdd, pullupVal );
69 }
70 
71 /**
72  @fn int CNanoI2CIOExpander::digitalRead( int input )
73  @brief Well knonwn function digitalRead applie to nanoI2CIOExpander but...
74  @param input the number of the input
75  @return the read value
76 
77  @warning input number from 0 to 10 corresponding to D2 to D12 on the nano
78 */
80  if ( input > 12 ) return 0;
81  int DRVal;
82  int regAdd;
83  regAdd = input<=7?DR:DR2;
84  DRVal = readRegister( regAdd );
85  return (int)bitRead( DRVal, input<=7?input:input-8 );
86 }
87 
88 void CNanoI2CIOExpander::digitalWrite( int output, int value ){
89  if ( output > 12 ) return;
90  int DRVal;
91  int regAdd;
92  // if ( input <= 7 ) regAdd = DR;
93  regAdd = output<=7?DR:DR2;
94  DRVal = readRegister( regAdd );
95  if (value) bitSet ( DRVal, output<=7?output:output-8 );
96  else bitClear(DRVal, output<=7?output:output-8);
97  writeRegister( regAdd, DRVal );
98 
99 }
100 
101 /**
102  @fn int CNanoI2CIOExpander::analogRead( int input)
103  @brief A method tha return 10bits value of one of the 6 analog inputs...
104  @param input analog input number from 0 to 5
105  @return read value
106 
107 Warning : mapping of analog inputs on ARDUINO Nano:
108 - 0 A0
109 - 1 A1
110 - 2 A2
111 - 3 A3
112 - 4 A6
113 - 5 A7
114 */
116  int lowAdd = 0;
117  if (input > 5 || input <0 )return 0;
118  switch ( input ){
119  case 0: lowAdd = 0X10; break;
120  case 1: lowAdd = 0X12; break;
121  case 2: lowAdd = 0X14; break;
122  case 3: lowAdd = 0X16; break;
123  case 4: lowAdd = 0X1C; break;
124  case 5: lowAdd = 0X1E; break;
125  }
126  lowAdd;
127  return readRegister( lowAdd )+ 256*readRegister( lowAdd+1);
128 
129 }
130 
131 /**
132  @fn int CNanoI2CIOExpander::readRegister( int add )
133  @brief Private method to read a 8 bits register in the NANO IO Expander
134  @param add is the addresse of the register to be read
135  @return the read value
136 */
137 int CNanoI2CIOExpander::readRegister( int add ){
138  Wire.beginTransmission(NANOEXP_ADDRESS);
139  Wire.write((uint8_t)add);
140  Wire.endTransmission();
141  Wire.requestFrom( (uint8_t)NANOEXP_ADDRESS, (uint8_t)1 );
142  return (int)Wire.read();
143 }
144 
145 /**
146  @fn void CNanoI2CIOExpander::writeRegister( int add, int val)
147  @brief Private method to write a 8 bits register in the NANO IO Expander
148  @param add the address of the register to be write
149  @param val the value to be write
150  @return nothing
151 */
152 void CNanoI2CIOExpander::writeRegister( int add, int val){
153  Wire.beginTransmission((uint8_t)NANOEXP_ADDRESS);
154  Wire.write((uint8_t)add);
155  Wire.write((uint8_t)val);
156  Wire.endTransmission();
157 }
158 
159 /**
160  @fn void CNanoI2CIOExpander::test()
161  @brief A special test method that use 2 special register to write and read and display
162  on the Serial monitor results...
163  @return true if all test is OK (new in 2.1 lib)
164 
165  first write 0x10 to register Test1 (reg add = 1)
166  and write 0x12 to register Test2 (reg add = 2)
167  and re-read the values and display them on Serial monitor
168 */
170  Serial.println( "Write 0x10 to 1");
171  writeRegister(1, 0X10);
172  Serial.println( "Write 0x12 to 2");
173  writeRegister(2, 0X12);
174  int retValReg1 = readRegister(1);
175  int retValReg2 = readRegister(2);
176  Serial.println( "Read of reg 1 = " + String( retValReg1, HEX ) );
177  Serial.println( "Read of reg 2 = " + String( retValReg2, HEX ) );
178  return ( (retValReg1 == 0X10) && (retValReg2 == 0X12) );
179 }
180 
181 /**
182  @fn void CFlasherNanoExp::begin( int pin, unsigned long ton, unsigned long toff)
183  @brief to prepare Led Flashing...
184  @param pin the pin number where the LED is connected (anode connection and cathod to ground) 0 to 7
185  @param ton time during the LED is switched on in milliseconds
186  @param toff time during the LED is switched off in milliseconds
187  @return no return value
188  This function puts pin in output mode and write it to 0 (low state ie off)
189 */
190 void CFlasherNanoExp::begin( int pin, unsigned long ton, unsigned long toff){
191  _pin = pin;
192  _ton = ton;
193  _toff = toff;
194  _ioexp.begin( _componentAdd );
195  _ioexp.pinMode( _pin, OUTPUT);
196  _ledState = 0;
197  _previousMillis = 0;
198  _changeStateCpt = 0;
199  Serial.println( "ici ");
200  _ioexp.digitalWrite( _pin, _ledState );
201  // _reverse= false;
202  _offLevel = 0;
203  _onLevel = 1;
204  _flashingMode = true;
205 
206 }
207 
208 /**
209  @fn void CFlasherNanoExp::begin( int pin, unsigned long ton, unsigned long toff,\
210  int repeat, unsigned long period)
211  @brief Method to start flasher in repeat mode...
212  @param pin same as in the normal implementation of begin
213  @param ton same as in the normal implementation of begin
214  @param toff same as in the normal implementation of begin
215  @param repeat number of repetitions
216  @param period total period
217  @return nothing
218 
219 period shall be greter then repeat*( ton + toff )
220 
221 and repeat shall be greater than 1
222 */
223 void CFlasherNanoExp::begin( int pin, unsigned long ton, unsigned long toff,\
224  int repeat, unsigned long period){
225  if ( ( repeat * ( ton + toff) < period ) && repeat >= 2 ){
226  _repeat = repeat;
227  _repeatCount = 0;
228  _period = period;
229  _previousPeriod = millis();
230  begin( pin, ton, toff );
231  }
232 
233  }
234 
235 /**
236 @fn void CFlasherNanoExp::update()
237 @brief This function should be call periodicly
238 @return no param and no return value
239 
240 Function check time with millis function and switch LED if necessary
241 */
243  // probably there is a best way to do this in more efficient codding style
244  if ( _flashingMode ){
245  if ( _repeat ){ //repeat mode
246  if ( _repeatCount < _repeat ){
247  if ( (millis()-_previousMillis > _ton) && (_ledState == _onLevel) ){
248  _ledState = _offLevel;
249  _previousMillis = millis();
250  _ioexp.digitalWrite( _pin, _ledState );
251  _changeStateCpt++;
252  _repeatCount++;
253  } else if ( (millis()-_previousMillis > _toff) && (_ledState == _offLevel) ){
254  _ledState = _onLevel ;
255  _previousMillis = millis();
256  _ioexp.digitalWrite( _pin, _ledState );
257  _changeStateCpt++;
258  }
259  } else if ( millis()-_previousPeriod > _period ){
260  _previousPeriod = millis();
261  _repeatCount = 0;
262  _previousMillis = millis();
263  }
264 
265  } else { //normal mode
266  if ( (millis()-_previousMillis > _ton) && (_ledState == _onLevel) ){
267  _ledState = _offLevel;
268  _previousMillis = millis();
269  _ioexp.digitalWrite( _pin, _ledState );
270  _changeStateCpt++;
271  } else if ( (millis()-_previousMillis > _toff) && (_ledState == _offLevel) ){
272  _ledState = _onLevel ;
273  _previousMillis = millis();
274  _ioexp.digitalWrite( _pin, _ledState );
275  _changeStateCpt++;
276  }
277  }
278  }
279 }
280 
281 /**
282 @fn void CFlasherNanoExp::stop()
283 @brief this function stop LED
284 @return no param and no return value
285 
286 Warning this function doesn't no prevent update() to work (except that the pin is in input mode)
287 */
289  _ioexp.digitalWrite( _pin, 0 );
290  _ledState = 0;
291  _ioexp.pinMode( _pin, INPUT );
292  _changeStateCpt = 0;
293  _repeat = 0;
294  _repeatCount = 0;
295  _period = 0;
296  _previousPeriod = 0;
297  // _reverse= false;
298  _offLevel = 0;
299  _onLevel = 1;
300  _flashingMode = false;
301 }
302 
303 /**
304  @fn void CFlasherNanoExp::reverseMode()
305  @brief Reverse the mode when it should be off it is on and conversely
306  @return no return value and no parameter
307 
308 A second call return to normal state
309 */
311  int tmp;
312  tmp = _offLevel;
313  _offLevel = _onLevel;
314  _onLevel = tmp;
315 
316 }
317 
318 /**
319  @fn void CFlasherNanoExp::high()
320  @brief to put led allways at ON state
321  @return no return value and no parameter
322 */
324  _ioexp.pinMode( _pin, OUTPUT );
325  _ioexp.digitalWrite( _pin, 1 );
326  _flashingMode = false;
327 }
328 
329 /**
330  @fn void CFlasherNanoExp::low()
331  @brief to put led allways at OFF state
332  @return no return value and no parameter
333 */
335  _ioexp.pinMode( _pin, OUTPUT );
336  _ioexp.digitalWrite( _pin, 0 );
337  _flashingMode = false;
338 }
#define DR
void pinMode(int output, int mode)
A method to set the pinMode but...
int digitalRead(int input)
Well knonwn function digitalRead applie to nanoI2CIOExpander but...
#define PULLUP2
void begin(int add=0x5F)
function that start the I2C protocol with nanoI2CIOExpander
void begin(int pin, unsigned long ton, unsigned long toff)
to prepare Led Flashing...
#define DDR
#define DDR2
void reverseMode()
Reverse the mode when it should be off it is on and conversely.
void digitalWrite(int output, int value)
#define PULLUP
Header file of the class CNanoI2CIOExpander...
void low()
to put led allways at OFF state
int analogRead(int input)
A method tha return 10bits value of one of the 6 analog inputs...
void stop()
this function stop LED
#define REGTEST3
#define NANOEXP_ADDRESS
void high()
to put led allways at ON state
bool test()
A special test method that use 2 special register to write and read and display on the Serial monitor...
void update()
This function should be call periodicly.
#define DR2