Skip to content

Commit ce597b7

Browse files
committed
Merge pull request arduino#93 from tbowmo/master
Testmode for Micro sensor
2 parents 4bd3151 + 3ab43d5 commit ce597b7

File tree

6 files changed

+1371
-54
lines changed

6 files changed

+1371
-54
lines changed

libraries/MySensors/examples/MysensorMicro/MysensorMicro.ino

Lines changed: 116 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Default sensor sketch for MySensor Micro module
22
// Act as a temperature / humidity sensor by default.
33
//
4-
// If A1 is held low while powering on, it will clear eeprom (and thereby the stored nodeid)
4+
// If A0 is held low while powering on, it will enter testmode, which verifies all on-board peripherals
55
//
66
// Battery voltage is repported as child sensorId 199, as well as battery percentage
77

@@ -10,7 +10,10 @@
1010
#include <Wire.h>
1111
#include <SI7021.h>
1212
#include <SPI.h>
13+
#include <SPIFlash.h>
1314
#include <EEPROM.h>
15+
#include <sha204_lib_return_codes.h>
16+
#include <sha204_library.h>
1417

1518
// Define a static node address, remove if you want auto address assignment
1619
//#define NODE_ADDRESS 3
@@ -21,15 +24,22 @@
2124
#define CHILD_ID_BATT 199
2225

2326
//Pin definitions
24-
#define RESET_CFG_PIN A1
27+
#define TEST_PIN A0
2528
#define LED_PIN A2
29+
#define ATSHA204_PIN 17 // A3
30+
31+
const int sha204Pin = ATSHA204_PIN;
32+
atsha204Class sha204(sha204Pin);
33+
2634

2735
#define MEASURE_INTERVAL 60000
2836

2937
// FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller
3038
#define FORCE_TRANSMIT_INTERVAL 30
3139

3240
SI7021 humiditySensor;
41+
SPIFlash flash(8, 0x1F65);
42+
3343
MySensor gw;
3444

3545
// Sensor messages
@@ -51,12 +61,14 @@ void setup() {
5161
pinMode(LED_PIN, OUTPUT);
5262
digitalWrite(LED_PIN, LOW);
5363

54-
// First check if we should boot into clear eeprom mode
55-
pinMode(RESET_CFG_PIN, INPUT);
56-
digitalWrite(RESET_CFG_PIN, HIGH); // Enable pullup
57-
if (!digitalRead(RESET_CFG_PIN)) resetEEP();
58-
digitalWrite(RESET_CFG_PIN, LOW);
64+
Serial.begin(115200);
65+
// First check if we should boot into test mode
66+
67+
pinMode(TEST_PIN,INPUT);
68+
digitalWrite(TEST_PIN, HIGH); // Enable pullup
69+
if (!digitalRead(TEST_PIN)) testMode();
5970

71+
digitalWrite(TEST_PIN,LOW);
6072
digitalWrite(LED_PIN, HIGH);
6173

6274
#ifdef NODE_ADDRESS
@@ -75,7 +87,7 @@ void setup() {
7587
gw.present(CHILD_ID_HUM,S_HUM);
7688

7789
gw.present(CHILD_ID_BATT, S_POWER);
78-
switchClock(1<<CLKPS2);
90+
switchClock(1<<CLKPS2); // Switch to 1Mhz for the reminder of the sketch, save power.
7991
}
8092

8193

@@ -173,21 +185,6 @@ long readVcc() {
173185
return result; // Vcc in millivolts
174186
}
175187

176-
177-
/*
178-
* Resets eeprom to default value (while blinking LED_PIN)
179-
*/
180-
void resetEEP()
181-
{
182-
for (int i=0;i<512;i++) {
183-
digitalWrite(LED_PIN, HIGH);
184-
delay(100);
185-
digitalWrite(LED_PIN, LOW);
186-
delay(100);
187-
EEPROM.write(i, 0xff);
188-
}
189-
}
190-
191188
void switchClock(unsigned char clk)
192189
{
193190
cli();
@@ -196,3 +193,99 @@ void switchClock(unsigned char clk)
196193
CLKPR = clk;
197194
sei();
198195
}
196+
197+
198+
// Verify all peripherals, and signal via the LED if any problems.
199+
void testMode()
200+
{
201+
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
202+
uint8_t ret_code;
203+
byte tests = 0;
204+
205+
digitalWrite(LED_PIN, HIGH); // Turn on LED.
206+
207+
Serial.println(F("Testing peripherals!"));
208+
Serial.print(F("-> SI7021 : "));
209+
delay(100);
210+
211+
if (humiditySensor.begin())
212+
{
213+
Serial.println(F("ok!"));
214+
tests ++;
215+
}
216+
else
217+
{
218+
Serial.println(F("failed!"));
219+
}
220+
delay(100);
221+
222+
Serial.print(F("-> Flash : "));
223+
delay(100);
224+
if (flash.initialize())
225+
{
226+
Serial.println(F("ok!"));
227+
tests ++;
228+
}
229+
else
230+
{
231+
Serial.println(F("failed!"));
232+
}
233+
delay(100);
234+
235+
Serial.println(F("-> SHA204 : "));
236+
ret_code = sha204.sha204c_wakeup(rx_buffer);
237+
if (ret_code != SHA204_SUCCESS)
238+
{
239+
Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX);
240+
}
241+
242+
if (ret_code == SHA204_SUCCESS)
243+
{
244+
ret_code = sha204.getSerialNumber(rx_buffer);
245+
if (ret_code != SHA204_SUCCESS)
246+
{
247+
Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX);
248+
}
249+
else
250+
{
251+
Serial.print(F("Device serial: "));
252+
for (int i=0; i<9; i++)
253+
{
254+
if (rx_buffer[i] < 0x10)
255+
{
256+
Serial.print('0'); // Because Serial.print does not 0-pad HEX
257+
}
258+
Serial.print(rx_buffer[i], HEX);
259+
}
260+
Serial.println();
261+
tests ++;
262+
}
263+
264+
}
265+
266+
267+
Serial.println(F("Test finished"));
268+
269+
if (tests == 3)
270+
{
271+
Serial.println(F("Selftest ok!"));
272+
while (1) // Blink OK pattern!
273+
{
274+
digitalWrite(LED_PIN, HIGH);
275+
delay(800);
276+
digitalWrite(LED_PIN, LOW);
277+
delay(200);
278+
}
279+
}
280+
else
281+
{
282+
Serial.println(F("----> Selftest failed!"));
283+
while (1) // Blink FAILED pattern! Rappidly blinking..
284+
{
285+
digitalWrite(LED_PIN, HIGH);
286+
delay(100);
287+
digitalWrite(LED_PIN, LOW);
288+
delay(100);
289+
}
290+
}
291+
}

libraries/SPIFlash/SPIFlash.cpp

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
* Minimal modifications should allow chips that have different page size but modifications
77
* DEPENDS ON: Arduino SPI library
88
*
9+
* Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment.
10+
* Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
11+
*
912
* This file is free software; you can redistribute it and/or modify
1013
* it under the terms of either the GNU General Public License version 2
1114
* or the GNU Lesser General Public License version 2.1, both as
@@ -32,33 +35,47 @@ SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) {
3235

3336
/// Select the flash chip
3437
void SPIFlash::select() {
35-
noInterrupts();
3638
//save current SPI settings
39+
#ifndef SPI_HAS_TRANSACTION
40+
_SREG = SREG;
41+
noInterrupts();
42+
#endif
3743
_SPCR = SPCR;
3844
_SPSR = SPSR;
39-
//set FLASH chip SPI settings
45+
46+
#ifdef SPI_HAS_TRANSACTION
47+
SPI.beginTransaction(_settings);
48+
#else
49+
// set FLASH SPI settings
4050
SPI.setDataMode(SPI_MODE0);
4151
SPI.setBitOrder(MSBFIRST);
42-
SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
43-
SPI.begin();
52+
SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
53+
#endif
4454
digitalWrite(_slaveSelectPin, LOW);
4555
}
4656

4757
/// UNselect the flash chip
4858
void SPIFlash::unselect() {
4959
digitalWrite(_slaveSelectPin, HIGH);
5060
//restore SPI settings to what they were before talking to the FLASH chip
61+
#ifdef SPI_HAS_TRANSACTION
62+
SPI.endTransaction();
63+
#else
64+
SREG = _SREG; // restore interrupts IFF they were enabled
65+
#endif
5166
SPCR = _SPCR;
5267
SPSR = _SPSR;
53-
interrupts();
5468
}
5569

5670
/// setup SPI, read device ID etc...
5771
boolean SPIFlash::initialize()
5872
{
5973
_SPCR = SPCR;
6074
_SPSR = SPSR;
75+
digitalWrite(_slaveSelectPin, HIGH);
6176
pinMode(_slaveSelectPin, OUTPUT);
77+
SPI.begin();
78+
_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);
6279
unselect();
6380
wakeup();
6481

@@ -185,22 +202,33 @@ void SPIFlash::writeByte(long addr, uint8_t byt) {
185202
unselect();
186203
}
187204

188-
/// write 1-256 bytes to flash memory
205+
/// write multiple bytes to flash memory (up to 64K)
189206
/// WARNING: you can only write to previously erased memory locations (see datasheet)
190207
/// use the block erase commands to first clear memory (write 0xFFs)
191-
/// WARNING: if you write beyond a page boundary (or more than 256bytes),
192-
/// the bytes will wrap around and start overwriting at the beginning of that same page
193-
/// see datasheet for more details
208+
/// This version handles both page alignment and data blocks larger than 256 bytes.
209+
///
194210
void SPIFlash::writeBytes(long addr, const void* buf, uint16_t len) {
195-
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
196-
SPI.transfer(addr >> 16);
197-
SPI.transfer(addr >> 8);
198-
SPI.transfer(addr);
199-
for (uint16_t i = 0; i < len; i++)
200-
SPI.transfer(((byte*) buf)[i]);
201-
unselect();
211+
uint16_t n;
212+
uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page
213+
uint16_t offset = 0;
214+
while (len>0)
215+
{
216+
n = (len<=maxBytes) ? len : maxBytes;
217+
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
218+
SPI.transfer(addr >> 16);
219+
SPI.transfer(addr >> 8);
220+
SPI.transfer(addr);
221+
for (uint16_t i = 0; i < n; i++)
222+
SPI.transfer(((byte*) buf)[offset + i]);
223+
unselect();
224+
addr+=n; // adjust the addresses and remaining bytes by what we've just transferred.
225+
offset +=n;
226+
len -= n;
227+
maxBytes = 256; // now we can do up to 256 bytes per loop
228+
}
202229
}
203230

231+
204232
/// erase entire flash memory array
205233
/// may take several seconds depending on size, but is non blocking
206234
/// so you may wait for this to complete using busy() or continue doing

libraries/SPIFlash/SPIFlash.h

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/*
22
* Copyright (c) 2013 by Felix Rusu <felix@lowpowerlab.com>
33
* SPI Flash memory library for arduino/moteino.
4-
* This works with 256byte/page SPI flash memory
5-
* For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes)
4+
* This works with 256uint8_t/page SPI flash memory
5+
* For instance a 4MBit (512Kuint8_t) flash chip will have 2048 pages: 256*2048 = 524288 uint8_ts (512Kuint8_ts)
66
* Minimal modifications should allow chips that have different page size but modifications
77
* DEPENDS ON: Arduino SPI library
88
*
9+
* Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
10+
*
911
* This file is free software; you can redistribute it and/or modify
1012
* it under the terms of either the GNU General Public License version 2
1113
* or the GNU Lesser General Public License version 2.1, both as
@@ -56,45 +58,51 @@
5658
// but no actual need to wait for completion (instead need to check the status register BUSY bit)
5759
#define SPIFLASH_STATUSREAD 0x05 // read status register
5860
#define SPIFLASH_STATUSWRITE 0x01 // write status register
59-
#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy byte after 3 address bytes)
61+
#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy uint8_t after 3 address uint8_ts)
6062
#define SPIFLASH_ARRAYREADLOWFREQ 0x03 // read array (low frequency)
6163

6264
#define SPIFLASH_SLEEP 0xB9 // deep power down
6365
#define SPIFLASH_WAKE 0xAB // deep power wake up
64-
#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256bytes)
65-
#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 bytes, specific bytes for each manufacturer and device)
66+
#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256uint8_ts)
67+
#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 uint8_ts, specific uint8_ts for each manufacturer and device)
6668
// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
6769
// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf)
6870
#define SPIFLASH_MACREAD 0x4B // read unique ID number (MAC)
6971

7072
class SPIFlash {
7173
public:
72-
static byte UNIQUEID[8];
73-
SPIFlash(byte slaveSelectPin, uint16_t jedecID=0);
74+
static uint8_t UNIQUEID[8];
75+
SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0);
7476
boolean initialize();
75-
void command(byte cmd, boolean isWrite=false);
76-
byte readStatus();
77-
byte readByte(long addr);
77+
void command(uint8_t cmd, boolean isWrite=false);
78+
uint8_t readStatus();
79+
uint8_t readByte(long addr);
7880
void readBytes(long addr, void* buf, word len);
79-
void writeByte(long addr, byte byt);
81+
void writeByte(long addr, uint8_t byt);
8082
void writeBytes(long addr, const void* buf, uint16_t len);
8183
boolean busy();
8284
void chipErase();
8385
void blockErase4K(long address);
8486
void blockErase32K(long address);
8587
word readDeviceId();
86-
byte* readUniqueId();
88+
uint8_t* readUniqueId();
8789

8890
void sleep();
8991
void wakeup();
9092
void end();
9193
protected:
9294
void select();
9395
void unselect();
94-
byte _slaveSelectPin;
96+
uint8_t _slaveSelectPin;
9597
uint16_t _jedecID;
96-
byte _SPCR;
97-
byte _SPSR;
98+
uint8_t _SPCR;
99+
uint8_t _SPSR;
100+
uint8_t _SREG;
101+
102+
#ifdef SPI_HAS_TRANSACTION
103+
SPISettings _settings;
104+
#endif
105+
98106
};
99107

100108
#endif

0 commit comments

Comments
 (0)