From a9261bc404244aab10613d6f1b25750a52d99444 Mon Sep 17 00:00:00 2001 From: Laurens Slats Date: Wed, 31 May 2017 16:15:32 +0200 Subject: [PATCH 1/7] Update README.md --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 643cd82..b5c246a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This repository includes example software to be used with the KISS LoRa gadget f ### Download this repository -Download the contents of this repository to your computer by clicking [here](archive/master.zip) or by going to **Clone or download->Download ZIP**. On your computer unzip the downloaded file by following the correct procedure for your operating system. +Download the contents of this repository to your computer by clicking [here](https://github.com/TheThingsIndustries/KISSLoRa-demo/archive/master.zip) or by clicking on the green button on top of this page: **Clone or download->Download ZIP**. On your computer unzip the downloaded file by following the correct procedure for your operating system. ### Arduino IDE @@ -50,7 +50,7 @@ Search for **SoftPWM** and click on **install**. 3. In the Arduino IDE make sure the correct **Tools->Board** (SparkFun Pro Micro) and **Tools->Processor** (ATmega 32U4, 8MHz) are selected. 4. Switch the device on and make sure the correct **Tools->Port** is selected. 5. Switch the device off again. -6. Press and hold the **Push Button** on the kiss device. +6. Press and hold the **Push Button** on the Kiss device. 6. In the Arduino IDE, choose **Sketch->Upload**. 7. As soon as you see `PORTS {} / {} => {}` printed in the output window turn KISSLoRa on. 8. When the upload process continue past showing `PORTS {} / {} => {}`, you can release the push button. @@ -68,6 +68,11 @@ If you are using MAC OS, [read this](https://learn.sparkfun.com/tutorials/how-to In the directory **KISSLoRa-demo_app** you will find the original firmware that was on the KISS LoRa device when you received it. If you ever want to flash this firmware back onto the device, have a look at the [README.md in this directory](KISSLoRa-demo_app/README.md). + +## [Examples](Examples) + +In the Examples directory you will find example firmware files to read the sensors on the board. Have a look at the README in each subdirectory to see an explanation of each example. + ## [Bootloader](Bootloader) In the Bootloader directory you will find the hex file for the bootloader that runs on your KISS LoRa device. In the most cases you will never need this, but if you manage to brick your device, this will be useful to recover. @@ -77,7 +82,3 @@ In the Bootloader directory you will find the hex file for the bootloader that r The Schematics directory contains the electronic design of the board. It specifically shows how everything is connected. This is useful to have when writing firmware for the KISS LoRa device, to know on which pins the sensors are connected. The schematic uses the pin names and numbers from the [datasheet of the ATmega32u4](Schematics/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf). When programming this board from within Arduino IDE, we use the Arduino pin names and numbers. See the [PIN_MAPPING](Schematics/PIN_MAPPING.md) document for the translation between these pin numbers and names. - -## [Examples](Examples) - -In the Examples directory you will find example firmware files to read the sensors on the board. Have a look at the README in each subdirectory to see an explanation of each example. From 0cc329394282c1877c89c7872ce69277b53b4723 Mon Sep 17 00:00:00 2001 From: Laurens Slats Date: Wed, 31 May 2017 16:39:37 +0200 Subject: [PATCH 2/7] Update README.md --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 643cd82..277b75f 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,19 @@ Search for **TheThingsNetwork** and click on **install**. Search for **SoftPWM** and click on **install**. + +### The Things Network Console + +Applications and devices can be managed via [The Things Network Console](https://console.thethingsnetwork.org/). In the Console you can find your application which is registered via the Commissioning Terminal. + +When uploading the new sketches, you need the `appEui` and `appKey`, you can find both in the Kiss-LoRa application which is registered under your personal account. Go to: +* [The Things Network Console](https://console.thethingsnetwork.org/) +* Click on *Applications* and select the `Kiss LoRa` application +* Click on *Devices* and select your `Kiss LoRa` device +* Go all the way to the bottom, under the `EXAMPLE CODE` you can find the keys you need later on + + + ## Uploading Firmware > The serial monitor must be closed before uploading code to the device. From 77955fa953489f81e863522b95159ce4567c7c13 Mon Sep 17 00:00:00 2001 From: jpmeijers Date: Thu, 1 Jun 2017 15:12:31 +0200 Subject: [PATCH 3/7] Add JosenePM example. --- Examples/JosenePM/IntemoPM.cpp | 96 +++++++++++++++++++++++++++ Examples/JosenePM/IntemoPM.h | 57 ++++++++++++++++ Examples/JosenePM/JosenePM.ino | 22 ++++++ Examples/JosenePM/README.md | 46 +++++++++++++ Examples/JosenePM/SC16IS752.cpp | 114 ++++++++++++++++++++++++++++++++ Examples/JosenePM/SC16IS752.h | 88 ++++++++++++++++++++++++ 6 files changed, 423 insertions(+) create mode 100644 Examples/JosenePM/IntemoPM.cpp create mode 100644 Examples/JosenePM/IntemoPM.h create mode 100644 Examples/JosenePM/JosenePM.ino create mode 100644 Examples/JosenePM/README.md create mode 100644 Examples/JosenePM/SC16IS752.cpp create mode 100644 Examples/JosenePM/SC16IS752.h diff --git a/Examples/JosenePM/IntemoPM.cpp b/Examples/JosenePM/IntemoPM.cpp new file mode 100644 index 0000000..5e54273 --- /dev/null +++ b/Examples/JosenePM/IntemoPM.cpp @@ -0,0 +1,96 @@ +/************************************************************************************ +* JosenePM.cpp - Library for JosenePM PM sensor * +* Copyright (c) 2014-2016 Antoine van de Cruyssen. All rights reserved * +* Edited for KISS LoRa compatibility by Rene Schalks. * +************************************************************************************* +* Rev 1.0 - September 2016 * +* - Initial release * +************************************************************************************* +* This library is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public * +* License as published by the Free Software Foundation; either * +* version 2.1 of the License, or (at your option) any later version. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this library; if not, write to the Free Software * +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * +************************************************************************************/ + +#include "IntemoPM.h" + +// Constructor +JosenePM::JosenePM() +{ + this->pm = new uint16_t[2]; +} + +//Initialize communication with the UART. +//Params: +//uint8_t UARTI2CAddress; The I2C address of the UART. This *SHOULD* be 0x4E. If not, check the datasheet for the proper address. It should be specified there. +//uint8_t UARTChannel; The channel the UART device sends data to. +void JosenePM::begin(uint8_t UARTI2CAddress, uint8_t UARTChannel) +{ + SC16IS752::begin(UARTI2CAddress,false); + SC16IS752::setup(PM,BAUD_9600,UART_8N1); + + SC16IS752::setGPIODir(0xFF); + //SC16IS752::writeGPIO(0x10); +} + +//Turns on the PM sensor. +void JosenePM::powerOn() { + SC16IS752::writeGPIO(SC16IS752::readGPIO() | 0x10); +} + +//Turns off the PM sensor. +void JosenePM::powerOff() { + SC16IS752::writeGPIO(SC16IS752::readGPIO() & 0xEF); +} + +//Retrieves the PM values from the sensor. +//Params: +//boolean dbg; Determines if the function should print the values to the Serial port. Can be ommitted, and is false by default. +//Returns: +//uint16_t[2]; an array of the retrieved PM values. The first index of this array contains the PM10 value, the second index contains the PM2.5 value. +uint16_t * JosenePM::getData(boolean dbg) +{ + uint8_t rx[63]={ }; + uint8_t x = SC16IS752::readUART_Array(PM,rx); + if(dbg==true) + { + for(uint8_t y = 0; y=10 && rx[0]==0xAA && rx[1]==0xC0 && rx[9]==0xAB) + { + this->pm[0]=((uint16_t)rx[5] << 8) | rx[4]; + this->pm[1]=((uint16_t)rx[3] << 8) | rx[2]; + //pm[1]; + if(dbg==true) { + Serial.print("PM10:"); Serial.print(this->pm[0]); Serial.print(" "); + Serial.print("PM2.5:"); Serial.print(this->pm[1]); Serial.print(" "); + Serial.println(""); + } + } + else + { + if(dbg==true) Serial.println(" ?"); + } + return this->pm; +} + +//Checks how much data is currently in the RX buffer. +//Returns: +//uint8_t; the amount of bytes currently in the RX buffer. +uint8_t JosenePM::checkRxLevel(uint8_t channel) +{ + return SC16IS752::checkRxLevel(channel); +} + diff --git a/Examples/JosenePM/IntemoPM.h b/Examples/JosenePM/IntemoPM.h new file mode 100644 index 0000000..4106aae --- /dev/null +++ b/Examples/JosenePM/IntemoPM.h @@ -0,0 +1,57 @@ +/************************************************************************************ +* JosenePM.h - Header for JosenePM PM sensor * +* Copyright (c) 2014-2016 Antoine van de Cruyssen. All rights reserved * +* Edited for KISS LoRa compatibility by Rene Schalks. * +************************************************************************************* +* Rev 1.0 - September 2016 * +* - Initial release * +************************************************************************************* +* This library is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public * +* License as published by the Free Software Foundation; either * +* version 2.1 of the License, or (at your option) any later version. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this library; if not, write to the Free Software * +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * +************************************************************************************/ +#ifndef JosenePM_h +#define JosenePM_h +#include +#include "SC16IS752.h" + +class JosenePM : public SC16IS752 +{ + private: + //An array of the latest retrieved PM values. + uint16_t *pm; + public: + JosenePM(); + //Initializes communication with the UART. + //Params: + //uint8_t UARTI2CAddress; The I2C address of the UART. This *SHOULD* be 0x4E. If not, check the datasheet for the proper address. It should be specified there. + //uint8_t UARTChannel; The channel the UART device sends data to. + void begin(uint8_t UARTI2CAddress, uint8_t UARTChannel); + //Retrieves the PM values from the sensor. + //Params: + //boolean dbg; Determines if the function should print the values to the Serial port. Can be ommitted, and is false by default. + //Returns: + //uint16_t[2]; an array of the retrieved PM values. The first index of this array contains the PM10 value, the second index contains the PM2.5 value. + uint16_t * getData(boolean dbg=false); + //Checks how much data is currently in the RX buffer. + //Returns: + //uint8_t; the amount of bytes currently in the RX buffer. + uint8_t checkRxLevel(uint8_t channel); + //Turns on the PM sensor. + void powerOn(); + //Turns off the PM sensor. + void powerOff(); +}; + +#endif + diff --git a/Examples/JosenePM/JosenePM.ino b/Examples/JosenePM/JosenePM.ino new file mode 100644 index 0000000..c1a2bcd --- /dev/null +++ b/Examples/JosenePM/JosenePM.ino @@ -0,0 +1,22 @@ +#include + +#define joseneAddress 0x4E + +JosenePM JosenePM; + +void setup() +{ + Serial.begin(9600); + + JosenePM.begin(joseneAddress, 1); + JosenePM.powerOn(); +} +void loop() +{ + uint16_t *data = JosenePM.getData(false); + Serial.print("Josene PM Data:\nPM10: "); + Serial.println(data[0]); + Serial.print("PM2.5: "); + Serial.println(data[1]); + delay(2000); +} diff --git a/Examples/JosenePM/README.md b/Examples/JosenePM/README.md new file mode 100644 index 0000000..3c08123 --- /dev/null +++ b/Examples/JosenePM/README.md @@ -0,0 +1,46 @@ +# Introduction + +At the E&A fair, in the boiler room, a few JosenePM sensors are available for experimentation. This example shows how to read the air quality form these devices, using your KISS LoRa gadget. + + +## Library usage +Copy both folders in /Libraries to (USER FOLDER)\Arduino\Libraries. +First, we need to enable the PM sensor class, then enable the physical PM sensor. +``` +#include + +#define joseneAddress 0x4E + +JosenePM JosenePM; + +void setup() +{ + Serial.begin(9600); + + JosenePM.begin(joseneAddress, 1); +} +``` +JosenePM.begin(uint8_t address, uint8_t channel) sends an initialization command to the sensor, setting it up to allow data transferring. +Then, we need to turn on the PM sensor. +``` +... + JosenePM.begin(joseneAddress, 1); + JosenePM.powerOn(); +} +``` +JosenePM.powerOn() turns on the sensor, allowing the device to register the amount of particles in its chamber, which is stored in an internal buffer. To retrieve the data, we use the following method: +``` +... +void loop() +{ + uint16_t *data = JosenePM.getData(false); + Serial.print("Josene PM Data:\nPM10: "); + Serial.println(data[0]); + Serial.print("PM2.5: "); + Serial.println(data[1]); + delay(2000); +} +``` +JosenePM.getData(boolean debug) reads the data from the device, and stores it in an array with a length of two unsigned, sixteen bit integers. The first element in the array is the PM10 value, the second element in the array is the PM2.5 value. + +**It is important to make sure a delay exists after reading, with at least 1.8 seconds. Otherwise, you will receive random values.** diff --git a/Examples/JosenePM/SC16IS752.cpp b/Examples/JosenePM/SC16IS752.cpp new file mode 100644 index 0000000..3de7449 --- /dev/null +++ b/Examples/JosenePM/SC16IS752.cpp @@ -0,0 +1,114 @@ +/************************************************************************************ +* SC16IS752.cpp - Library for SC16IS752 dual uart * +* Copyright (c) 2014-2016 Antoine van de Cruyssen. All rights reserved * +* Edited by Rene Schalks to be compatible with KISS LoRa. * +************************************************************************************* +* Rev 1.0 - September 2016 * +* - Initial release * +************************************************************************************* +* This library is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public * +* License as published by the Free Software Foundation; either * +* version 2.1 of the License, or (at your option) any later version. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this library; if not, write to the Free Software * +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * +************************************************************************************/ + +#include "SC16IS752.h" +//i2c_device Test; + +// Constructor +SC16IS752::SC16IS752() +{ + +} + +void SC16IS752::begin(uint8_t Address, boolean TWI_Begin) +{ + this->Address = Address; + if (TWI_Begin) + { + I2c.begin(); + } + //i2c_device::begin(Address, TWI_Begin); +} + +/**************** +* Channel Setup * +****************/ +void SC16IS752::setup(uint8_t Channel, uint8_t BaudrateDevisor, uint8_t LineControl) +{ + SC16IS752::writeUART(LCR, Channel, 0x80); // 0x80 to program baud rate divisor + SC16IS752::writeUART(DLL, Channel, BaudrateDevisor); // 12=9600 baud + SC16IS752::writeUART(DLH, Channel, 0x00); + SC16IS752::writeUART(LCR, Channel, 0xBF); // access EFR register + SC16IS752::writeUART(EFR, Channel, 0x10); // enable enhanced registers + SC16IS752::writeUART(LCR, Channel, LineControl); // 8 data bits, 1 stop bit, no parity + SC16IS752::writeUART(FCR, Channel, 0x07); // reset TXFIFO, reset RXFIFO, enable FIFO mode +} + +/********************* +* Write data to UART * +*********************/ +void SC16IS752::writeUART(uint8_t RegAddr, uint8_t Channel, uint8_t Data) +{ + I2c.write(this->Address, ((RegAddr << 3) | (Channel << 1)), Data); +} + +/*********************** +* Read array from UART * +***********************/ +uint8_t SC16IS752::readUART_Array(uint8_t Channel, uint8_t *Data) +{ + uint8_t num = SC16IS752::checkRxLevel(Channel); + I2c.read(this->Address, ((RHR << 3) | (Channel << 1)), num, Data); + //i2c_device::read_many(((RHR << 3) | (Channel << 1)), num, Data); + return num; +} + +/****************************** +* Get number of bytes in FIFO * +******************************/ +uint8_t SC16IS752::checkRxLevel(uint8_t Channel) +{ + byte result; + I2c.read(this->Address, ((RXLVL << 3) | (Channel << 1)) & 0x7F, 1, &result); + return result; + //return i2c_device::read(((RXLVL << 3) | (Channel << 1)) & 0x7F); +} + +/************************************ +* Set GPIO directions * +* GPIO0 to GPIO7, 0=input, 1=Output * +************************************/ +void SC16IS752::setGPIODir(uint8_t Bits) { + I2c.write(this->Address, (IOControl << 3), 0x00); + I2c.write(this->Address, (IODir << 3), Bits); +} + +/******************* +* Read GPIO inputs * +* GPIO0 to GPIO7 * +*******************/ +uint8_t SC16IS752::readGPIO() { + //return readI2c(IOState << 3); + byte result; + I2c.read(this->Address, IOState << 3, 1, &result); + return result; +} + +/********************* +* Write GPIO outputs * +* GPIO0 to GPIO7 * +*********************/ +void SC16IS752::writeGPIO(uint8_t Data) { + I2c.write(this->Address, (IOState << 3), Data); +} + diff --git a/Examples/JosenePM/SC16IS752.h b/Examples/JosenePM/SC16IS752.h new file mode 100644 index 0000000..3713ed9 --- /dev/null +++ b/Examples/JosenePM/SC16IS752.h @@ -0,0 +1,88 @@ +/************************************************************************************ +* SC16IS752.h - Header for SC16IS752 dual uart * +* Copyright (c) 2014-2016 Antoine van de Cruyssen. All rights reserved * +************************************************************************************* +* Rev 1.0 - September 2016 * +* - Initial release * +************************************************************************************* +* This library is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public * +* License as published by the Free Software Foundation; either * +* version 2.1 of the License, or (at your option) any later version. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this library; if not, write to the Free Software * +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * +************************************************************************************/ +#ifndef SC16IS752_h +#define SC16IS752_h +#include +//#include +#include "I2C.h" + +#define RHR 0x00 // Recv Holding Register is 0x00 in READ Mode +#define THR 0x00 // Xmit Holding Register is 0x00 in WRITE Mode +#define IER 0x01 // Interrupt Enable Register +#define IIR 0x02 // Interrupt Identification Register in READ Mode +#define FCR 0x02 // FIFO Control Register in WRITE Mode +#define LCR 0x03 // Line Control Register +#define MCR 0x04 // Modem Control Register +#define LSR 0x05 // Line status Register +#define MSR 0x06 // Modem Status Register +#define SPR 0x07 // ScratchPad Register +#define TCR 0x06 // Transmission Control Register +#define TLR 0x07 // Trigger Level Register +#define TXLVL 0x08 // Xmit FIFO Level Register +#define RXLVL 0x09 // Recv FIFO Level Register +#define IODir 0x0A // I/O P:ins Direction Register +#define IOState 0x0B // I/O Pins State Register +#define IOIntEna 0x0C // I/O Interrupt Enable Register +#define IOControl 0x0E // I/O Pins Control Register +#define EFCR 0x0F // Extra Features Control Register + + +#define DLL 0x00 // Divisor Latch LSB 0x00 +#define DLH 0x01 // Divisor Latch MSB 0x01 +#define EFR 0x02 // Enhanced Function Register +#define XON1 0x04 +#define XON2 0x05 +#define XOFF1 0x06 +#define XOFF2 0x07 + +#define I2CWRITE 0x00 +#define I2CREAD 0x01 + +#define CHANA 0 +#define CHANB 1 + +#define UART_8N1 0x03 +#define UART_8E1 0x1B +#define BAUD_9600 0x0C +#define BAUD_19200 0x06 + +#define CO2 0 +#define PM 1 + +class SC16IS752 +{ + private: + int Address; + public: + SC16IS752(); + void begin(uint8_t Address, boolean TWI_Begin); + void setup(uint8_t Channel, uint8_t BaudrateDevisor, uint8_t LineControl); + void writeUART(uint8_t RegAddr, uint8_t Channel, uint8_t Data); + uint8_t readUART_Array(uint8_t Channel, uint8_t *Data); + void setGPIODir(uint8_t Bits); + uint8_t readGPIO(); + uint8_t checkRxLevel(uint8_t Channel); + void writeGPIO(uint8_t Data); +}; + +#endif + From 88611a330e6b72ab1783d340097f4bdc2f9595e8 Mon Sep 17 00:00:00 2001 From: jpmeijers Date: Thu, 1 Jun 2017 15:14:49 +0200 Subject: [PATCH 4/7] Make JosenePM compilable --- Examples/JosenePM/I2C.cpp | 709 +++++++++++++++++++++++++++++++++ Examples/JosenePM/I2C.h | 135 +++++++ Examples/JosenePM/JosenePM.ino | 2 +- 3 files changed, 845 insertions(+), 1 deletion(-) create mode 100644 Examples/JosenePM/I2C.cpp create mode 100644 Examples/JosenePM/I2C.h diff --git a/Examples/JosenePM/I2C.cpp b/Examples/JosenePM/I2C.cpp new file mode 100644 index 0000000..1202f31 --- /dev/null +++ b/Examples/JosenePM/I2C.cpp @@ -0,0 +1,709 @@ +/* + I2C.cpp - I2C library + Copyright (c) 2011-2012 Wayne Truchsess. All right reserved. + Rev 5.0 - January 24th, 2012 + - Removed the use of interrupts completely from the library + so TWI state changes are now polled. + - Added calls to lockup() function in most functions + to combat arbitration problems + - Fixed scan() procedure which left timeouts enabled + and set to 80msec after exiting procedure + - Changed scan() address range back to 0 - 0x7F + - Removed all Wire legacy functions from library + - A big thanks to Richard Baldwin for all the testing + and feedback with debugging bus lockups! + Rev 4.0 - January 14th, 2012 + - Updated to make compatible with 8MHz clock frequency + Rev 3.0 - January 9th, 2012 + - Modified library to be compatible with Arduino 1.0 + - Changed argument type from boolean to uint8_t in pullUp(), + setSpeed() and receiveByte() functions for 1.0 compatability + - Modified return values for timeout feature to report + back where in the transmission the timeout occured. + - added function scan() to perform a bus scan to find devices + attached to the I2C bus. Similar to work done by Todbot + and Nick Gammon + Rev 2.0 - September 19th, 2011 + - Added support for timeout function to prevent + and recover from bus lockup (thanks to PaulS + and CrossRoads on the Arduino forum) + - Changed return type for stop() from void to + uint8_t to handle timeOut function + Rev 1.0 - August 8th, 2011 + + This is a modified version of the Arduino Wire/TWI + library. Functions were rewritten to provide more functionality + and also the use of Repeated Start. Some I2C devices will not + function correctly without the use of a Repeated Start. The + initial version of this library only supports the Master. + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if(ARDUINO >= 100) +#include +#else +#include +#endif + +#include +#include "I2C.h" + + + +uint8_t I2C::bytesAvailable = 0; +uint8_t I2C::bufferIndex = 0; +uint8_t I2C::totalBytes = 0; +uint16_t I2C::timeOutDelay = 0; + +I2C::I2C() +{ +} + + +////////////// Public Methods //////////////////////////////////////// + + + +void I2C::begin() +{ + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // activate internal pull-ups for twi + // as per note from atmega8 manual pg167 + sbi(PORTC, 4); + sbi(PORTC, 5); + #else + // activate internal pull-ups for twi + // as per note from atmega128 manual pg204 + sbi(PORTD, 0); + sbi(PORTD, 1); + #endif + // initialize twi prescaler and bit rate + cbi(TWSR, TWPS0); + cbi(TWSR, TWPS1); + TWBR = ((F_CPU / 100000) - 16) / 2; + // enable twi module and acks + TWCR = _BV(TWEN) | _BV(TWEA); +} + +void I2C::end() +{ + TWCR = 0; +} + +void I2C::timeOut(uint16_t _timeOut) +{ + timeOutDelay = _timeOut; +} + +void I2C::setSpeed(uint8_t _fast) +{ + if(!_fast) + { + TWBR = ((F_CPU / 100000) - 16) / 2; + } + else + { + TWBR = ((F_CPU / 400000) - 16) / 2; + } +} + +void I2C::pullup(uint8_t activate) +{ + if(activate) + { + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // activate internal pull-ups for twi + // as per note from atmega8 manual pg167 + sbi(PORTC, 4); + sbi(PORTC, 5); + #else + // activate internal pull-ups for twi + // as per note from atmega128 manual pg204 + sbi(PORTD, 0); + sbi(PORTD, 1); + #endif + } + else + { + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // deactivate internal pull-ups for twi + // as per note from atmega8 manual pg167 + cbi(PORTC, 4); + cbi(PORTC, 5); + #else + // deactivate internal pull-ups for twi + // as per note from atmega128 manual pg204 + cbi(PORTD, 0); + cbi(PORTD, 1); + #endif + } +} + +void I2C::scan() +{ + uint16_t tempTime = timeOutDelay; + timeOut(80); + uint8_t totalDevicesFound = 0; + Serial.println("Scanning for devices...please wait"); + Serial.println(); + for(uint8_t s = 0; s <= 0x7F; s++) + { + returnStatus = 0; + returnStatus = start(); + if(!returnStatus) + { + returnStatus = sendAddress(SLA_W(s)); + } + if(returnStatus) + { + if(returnStatus == 1) + { + Serial.println("There is a problem with the bus, could not complete scan"); + timeOutDelay = tempTime; + return; + } + } + else + { + Serial.print("Found device at address - "); + Serial.print(" 0x"); + Serial.println(s,HEX); + totalDevicesFound++; + } + stop(); + } + if(!totalDevicesFound){Serial.println("No devices found");} + timeOutDelay = tempTime; +} + + +uint8_t I2C::available() +{ + return(bytesAvailable); +} + +uint8_t I2C::receive() +{ + bufferIndex = totalBytes - bytesAvailable; + if(!bytesAvailable) + { + bufferIndex = 0; + return(0); + } + bytesAvailable--; + return(data[bufferIndex]); +} + + +/*return values for new functions that use the timeOut feature + will now return at what point in the transmission the timeout + occurred. Looking at a full communication sequence between a + master and slave (transmit data and then readback data) there + a total of 7 points in the sequence where a timeout can occur. + These are listed below and correspond to the returned value: + 1 - Waiting for successful completion of a Start bit + 2 - Waiting for ACK/NACK while addressing slave in transmit mode (MT) + 3 - Waiting for ACK/NACK while sending data to the slave + 4 - Waiting for successful completion of a Repeated Start + 5 - Waiting for ACK/NACK while addressing slave in receiver mode (MR) + 6 - Waiting for ACK/NACK while receiving data from the slave + 7 - Waiting for successful completion of the Stop bit + + All possible return values: + 0 Function executed with no errors + 1 - 7 Timeout occurred, see above list + 8 - 0xFF See datasheet for exact meaning */ + + +///////////////////////////////////////////////////// + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus) + { + if(returnStatus == 1){return(2);} + return(returnStatus); + } + returnStatus = sendByte(registerAddress); + if(returnStatus) + { + if(returnStatus == 1){return(3);} + return(returnStatus); + } + returnStatus = stop(); + if(returnStatus) + { + if(returnStatus == 1){return(7);} + return(returnStatus); + } + return(returnStatus); +} + +uint8_t I2C::write(int address, int registerAddress) +{ + return(write((uint8_t) address, (uint8_t) registerAddress)); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t data) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus) + { + if(returnStatus == 1){return(2);} + return(returnStatus); + } + returnStatus = sendByte(registerAddress); + if(returnStatus) + { + if(returnStatus == 1){return(3);} + return(returnStatus); + } + returnStatus = sendByte(data); + if(returnStatus) + { + if(returnStatus == 1){return(3);} + return(returnStatus); + } + returnStatus = stop(); + if(returnStatus) + { + if(returnStatus == 1){return(7);} + return(returnStatus); + } + return(returnStatus); +} + +uint8_t I2C::write(int address, int registerAddress, int data) +{ + return(write((uint8_t) address, (uint8_t) registerAddress, (uint8_t) data)); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, char *data) +{ + uint8_t bufferLength = strlen(data); + returnStatus = 0; + returnStatus = write(address, registerAddress, (uint8_t*)data, bufferLength); + return(returnStatus); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t *data, uint8_t numberBytes) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus) + { + if(returnStatus == 1){return(2);} + return(returnStatus); + } + returnStatus = sendByte(registerAddress); + if(returnStatus) + { + if(returnStatus == 1){return(3);} + return(returnStatus); + } + for (uint8_t i = 0; i < numberBytes; i++) + { + returnStatus = sendByte(data[i]); + if(returnStatus) + { + if(returnStatus == 1){return(3);} + return(returnStatus); + } + } + returnStatus = stop(); + if(returnStatus) + { + if(returnStatus == 1){return(7);} + return(returnStatus); + } + return(returnStatus); +} + +uint8_t I2C::read(int address, int numberBytes) +{ + return(read((uint8_t) address, (uint8_t) numberBytes)); +} + +uint8_t I2C::read(uint8_t address, uint8_t numberBytes) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus) + { + if(returnStatus == 1){return(5);} + return(returnStatus); + } + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus == 1){return(6);} + + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus == 1){return(6);} + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + data[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + if(returnStatus) + { + if(returnStatus == 1){return(7);} + return(returnStatus); + } + return(returnStatus); +} + +uint8_t I2C::read(int address, int registerAddress, int numberBytes) +{ + return(read((uint8_t) address, (uint8_t) registerAddress, (uint8_t) numberBytes)); +} + +uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus) + { + if(returnStatus == 1){return(2);} + return(returnStatus); + } + returnStatus = sendByte(registerAddress); + if(returnStatus) + { + if(returnStatus == 1){return(3);} + return(returnStatus); + } + returnStatus = start(); + if(returnStatus) + { + if(returnStatus == 1){return(4);} + return(returnStatus); + } + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus) + { + if(returnStatus == 1){return(5);} + return(returnStatus); + } + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus == 1){return(6);} + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus == 1){return(6);} + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + data[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + if(returnStatus) + { + if(returnStatus == 1){return(7);} + return(returnStatus); + } + return(returnStatus); +} + +uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus) + { + if(returnStatus == 1){return(5);} + return(returnStatus); + } + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus == 1){return(6);} + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus == 1){return(6);} + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + dataBuffer[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + if(returnStatus) + { + if(returnStatus == 1){return(7);} + return(returnStatus); + } + return(returnStatus); +} + +uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes, uint8_t *dataBuffer) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus) + { + if(returnStatus == 1){return(2);} + return(returnStatus); + } + returnStatus = sendByte(registerAddress); + if(returnStatus) + { + if(returnStatus == 1){return(3);} + return(returnStatus); + } + returnStatus = start(); + if(returnStatus) + { + if(returnStatus == 1){return(4);} + return(returnStatus); + } + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus) + { + if(returnStatus == 1){return(5);} + return(returnStatus); + } + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus == 1){return(6);} + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus == 1){return(6);} + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + dataBuffer[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + if(returnStatus) + { + if(returnStatus == 1){return(7);} + return(returnStatus); + } + return(returnStatus); +} + + +/////////////// Private Methods //////////////////////////////////////// + + +uint8_t I2C::start() +{ + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START)) + { + return(0); + } + if (TWI_STATUS == LOST_ARBTRTN) + { + uint8_t bufferedStatus = TWI_STATUS; + lockUp(); + return(bufferedStatus); + } + return(TWI_STATUS); +} + +uint8_t I2C::sendAddress(uint8_t i2cAddress) +{ + TWDR = i2cAddress; + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if ((TWI_STATUS == MT_SLA_ACK) || (TWI_STATUS == MR_SLA_ACK)) + { + return(0); + } + uint8_t bufferedStatus = TWI_STATUS; + if ((TWI_STATUS == MT_SLA_NACK) || (TWI_STATUS == MR_SLA_NACK)) + { + stop(); + return(bufferedStatus); + } + else + { + lockUp(); + return(bufferedStatus); + } +} + +uint8_t I2C::sendByte(uint8_t i2cData) +{ + TWDR = i2cData; + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if (TWI_STATUS == MT_DATA_ACK) + { + return(0); + } + uint8_t bufferedStatus = TWI_STATUS; + if (TWI_STATUS == MT_DATA_NACK) + { + stop(); + return(bufferedStatus); + } + else + { + lockUp(); + return(bufferedStatus); + } +} + +uint8_t I2C::receiveByte(uint8_t ack) +{ + unsigned long startingTime = millis(); + if(ack) + { + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + } + if (TWI_STATUS == LOST_ARBTRTN) + { + uint8_t bufferedStatus = TWI_STATUS; + lockUp(); + return(bufferedStatus); + } + return(TWI_STATUS); +} + +uint8_t I2C::stop() +{ + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + return(0); +} + +void I2C::lockUp() +{ + TWCR = 0; //releases SDA and SCL lines to high impedance + TWCR = _BV(TWEN) | _BV(TWEA); //reinitialize TWI +} + +I2C I2c = I2C(); + diff --git a/Examples/JosenePM/I2C.h b/Examples/JosenePM/I2C.h new file mode 100644 index 0000000..2609f7a --- /dev/null +++ b/Examples/JosenePM/I2C.h @@ -0,0 +1,135 @@ +/* + I2C.h - I2C library + Copyright (c) 2011-2012 Wayne Truchsess. All right reserved. + Rev 5.0 - January 24th, 2012 + - Removed the use of interrupts completely from the library + so TWI state changes are now polled. + - Added calls to lockup() function in most functions + to combat arbitration problems + - Fixed scan() procedure which left timeouts enabled + and set to 80msec after exiting procedure + - Changed scan() address range back to 0 - 0x7F + - Removed all Wire legacy functions from library + - A big thanks to Richard Baldwin for all the testing + and feedback with debugging bus lockups! + Rev 4.0 - January 14th, 2012 + - Updated to make compatible with 8MHz clock frequency + Rev 3.0 - January 9th, 2012 + - Modified library to be compatible with Arduino 1.0 + - Changed argument type from boolean to uint8_t in pullUp(), + setSpeed() and receiveByte() functions for 1.0 compatability + - Modified return values for timeout feature to report + back where in the transmission the timeout occured. + - added function scan() to perform a bus scan to find devices + attached to the I2C bus. Similar to work done by Todbot + and Nick Gammon + Rev 2.0 - September 19th, 2011 + - Added support for timeout function to prevent + and recover from bus lockup (thanks to PaulS + and CrossRoads on the Arduino forum) + - Changed return type for stop() from void to + uint8_t to handle timeOut function + Rev 1.0 - August 8th, 2011 + + This is a modified version of the Arduino Wire/TWI + library. Functions were rewritten to provide more functionality + and also the use of Repeated Start. Some I2C devices will not + function correctly without the use of a Repeated Start. The + initial version of this library only supports the Master. + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if(ARDUINO >= 100) +#include +#else +#include +#endif + +#include + +#ifndef I2C_h +#define I2C_h + + +#define START 0x08 +#define REPEATED_START 0x10 +#define MT_SLA_ACK 0x18 +#define MT_SLA_NACK 0x20 +#define MT_DATA_ACK 0x28 +#define MT_DATA_NACK 0x30 +#define MR_SLA_ACK 0x40 +#define MR_SLA_NACK 0x48 +#define MR_DATA_ACK 0x50 +#define MR_DATA_NACK 0x58 +#define LOST_ARBTRTN 0x38 +#define TWI_STATUS (TWSR & 0xF8) +#define SLA_W(address) (address << 1) +#define SLA_R(address) ((address << 1) + 0x01) +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + +#define MAX_BUFFER_SIZE 32 + + + + +class I2C +{ + public: + I2C(); + void begin(); + void end(); + void timeOut(uint16_t); + void setSpeed(uint8_t); + void pullup(uint8_t); + void scan(); + uint8_t available(); + uint8_t receive(); + uint8_t write(uint8_t, uint8_t); + uint8_t write(int, int); + uint8_t write(uint8_t, uint8_t, uint8_t); + uint8_t write(int, int, int); + uint8_t write(uint8_t, uint8_t, char*); + uint8_t write(uint8_t, uint8_t, uint8_t*, uint8_t); + uint8_t read(uint8_t, uint8_t); + uint8_t read(int, int); + uint8_t read(uint8_t, uint8_t, uint8_t); + uint8_t read(int, int, int); + uint8_t read(uint8_t, uint8_t, uint8_t*); + uint8_t read(uint8_t, uint8_t, uint8_t, uint8_t*); + + + private: + uint8_t start(); + uint8_t sendAddress(uint8_t); + uint8_t sendByte(uint8_t); + uint8_t receiveByte(uint8_t); + uint8_t stop(); + void lockUp(); + uint8_t returnStatus; + uint8_t nack; + uint8_t data[MAX_BUFFER_SIZE]; + static uint8_t bytesAvailable; + static uint8_t bufferIndex; + static uint8_t totalBytes; + static uint16_t timeOutDelay; + +}; + +extern I2C I2c; + +#endif diff --git a/Examples/JosenePM/JosenePM.ino b/Examples/JosenePM/JosenePM.ino index c1a2bcd..c098123 100644 --- a/Examples/JosenePM/JosenePM.ino +++ b/Examples/JosenePM/JosenePM.ino @@ -1,4 +1,4 @@ -#include +#include "IntemoPM.h" #define joseneAddress 0x4E From c6486d8047ded9b1f69f091ab993854735e07f7d Mon Sep 17 00:00:00 2001 From: jpmeijers Date: Fri, 2 Jun 2017 17:26:57 +0200 Subject: [PATCH 5/7] Remove random SF from LoRa example. Was only there for increased capacity during the fair. --- Examples/LoRa_TX_RX/LoRa_TX_RX.ino | 62 +----------------------------- Examples/LoRa_TX_RX/README.md | 10 ++--- 2 files changed, 6 insertions(+), 66 deletions(-) diff --git a/Examples/LoRa_TX_RX/LoRa_TX_RX.ino b/Examples/LoRa_TX_RX/LoRa_TX_RX.ino index 265927c..29e68ae 100644 --- a/Examples/LoRa_TX_RX/LoRa_TX_RX.ino +++ b/Examples/LoRa_TX_RX/LoRa_TX_RX.ino @@ -56,9 +56,6 @@ void setup() debugSerial.println("-- JOIN"); ttn.join(appEui, appKey); - - // Seed the random function - seedRandomFunction(); } void loop() @@ -74,8 +71,8 @@ void loop() byte payload[1]; payload[0] = getRotaryPosition(); - // Send the payload, on port 2, not asking for an ack, using the random SF - ttn.sendBytes(payload, sizeof(payload), 2, false, getSF()); + // Send the payload, on port 2 + ttn.sendBytes(payload, sizeof(payload), 2); delay(10000); } @@ -131,58 +128,3 @@ int8_t getRotaryPosition() return value; } - -void seedRandomFunction() -{ - char hwEui_char_array[16+1];//16 chars + \0 - uint16_t hwEui_16_bits = 0; - - ttn.getHardwareEui(hwEui_char_array, 17); //read HWEUI from module - hwEui_16_bits = ascii_hex_to_nibble(hwEui_char_array[12]); - hwEui_16_bits |= ascii_hex_to_nibble(hwEui_char_array[13]) << 4; - hwEui_16_bits |= ascii_hex_to_nibble(hwEui_char_array[14]) << 8; - hwEui_16_bits |= ascii_hex_to_nibble(hwEui_char_array[15]) << 12; - uint16_t seed = hwEui_16_bits; - randomSeed(seed); -} - -uint8_t getSF() -{ - uint8_t txsf = 7; - uint8_t rnd = (uint8_t)random(1, 64); - - if (rnd == 1 ) { - txsf = 12; // SF12 - } - else if (rnd > 1 && rnd < 4 ) { - txsf = 11; // SF11 - } - else if (rnd > 3 && rnd < 8 ) { - txsf = 10; // SF10 - } - else if (rnd > 7 && rnd < 16 ) { - txsf = 9; // SF9 - } - else if (rnd > 15 && rnd < 32 ) { - txsf = 8; // SF8 - } - else { - txsf = 7; // SF7 - } -} - -//This function is used to convert ascii-hex string to integer -static uint8_t ascii_hex_to_nibble(char ascii_hex) -{ - uint8_t return_value=0; - - if((ascii_hex >= 'A') && (ascii_hex <= 'F')) - { - return_value |= (ascii_hex - ('A' - 10)); - } - else if((ascii_hex >= '0') && (ascii_hex <= '9')) - { - return_value |= (ascii_hex - '0'); - } - return return_value; -} diff --git a/Examples/LoRa_TX_RX/README.md b/Examples/LoRa_TX_RX/README.md index a037e7f..00baf24 100644 --- a/Examples/LoRa_TX_RX/README.md +++ b/Examples/LoRa_TX_RX/README.md @@ -4,7 +4,7 @@ This example periodically sends a message via The Things Network LoRaWAN network To use this example you have to register a device on [The Things Network Console](https://console.thethingsnetwork.org/applications). -When registering a device you will need the device's EUI. To obtain this, upload this firmware, run it, and in the Serial Monitor you should see an output looking like the following: +When registering a device you will need the device's EUI. To obtain the EUI, upload this firmware, run it, and in the Serial Monitor you should see an output looking like the following: ``` -- STATUS @@ -17,9 +17,9 @@ RX Delay 1: 1000 RX Delay 2: 2000 ``` -Copy the code after EUI, consisting of 16 hex character, and use that when registering your device on the TTN console. +Copy the code after EUI or DevEUI (they should be the same), consisting of 16 hex character, and use this when registering your device on the TTN console. -After registering your device, at the bottom of the device page, you should see some example code. Copy this code and replace the place holder code at the top of this example that looks as follows: +After registering your device, at the bottom of the device page, you should see some example code. Copy this code and replace the place-holder code at the top of this example that looks as follows: ``` // Set your AppEUI and AppKey @@ -35,8 +35,6 @@ delay(30000); //remove this after you registered your device -When you use this firmware on your KISS device, it will poll the network for a downlink message, wait 10 seconds, send the position of the rotary switch and check for downlink messages, wait another 10 seconds, and continue doing the same in a loop. +When you use this firmware on your KISS gadget, it will poll the network for a downlink message, wait 10 seconds, send the position of the rotary switch and check for downlink messages, wait another 10 seconds, and continue doing the same in a loop. On the TTN console you should see the rotary switch position arriving on port 2, and the polling messages on port 1. You can send some downlink message using the "Downlink" form on the console. The data you type in the payload field should be HEX characters. When the KISS device receives a downlink message, it will toggle the red LED. - -This firmware chooses a random Spreading Factor to transmit the LoRa message on, using a specific probability density function designed to optimise the capacity of the LoRaWAN network. The biggest part of this example is made up of the code to compute this random SF. \ No newline at end of file From 765d9642d3630a1e6c7533e9ea3ead6779336470 Mon Sep 17 00:00:00 2001 From: jpmeijers Date: Fri, 2 Jun 2017 17:50:18 +0200 Subject: [PATCH 6/7] FAQ at top of readme, link to FAQ and commissioning steps. --- COMMISSION_AT_HOME.md | 29 +++++++++++++++++++++++++++++ README.md | 12 +++++++----- 2 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 COMMISSION_AT_HOME.md diff --git a/COMMISSION_AT_HOME.md b/COMMISSION_AT_HOME.md new file mode 100644 index 0000000..6cfaff3 --- /dev/null +++ b/COMMISSION_AT_HOME.md @@ -0,0 +1,29 @@ +# Commissioning + +During the E&A fair we had a couple of commissioning stations standing around where one could personalise, or commission, your KISS gadget. It is however also possible to commission the device without the commissioning stations. These stations did automate many steps, so at home the process is more complex. + +## Prerequisites + +* Follow the steps in the main README to install the latest version of the Arduino IDE. +* Also install the USB drivers, SparkFun AVR boards and TheThingsNetwork library. +* [A TTN account](https://account.thethingsnetwork.org/) + +## Device info + +In the Arduino IDE, go to **File->Examples->TheThingsNetwork->DeviceInfo**. This will open the Device Info example code. On line 7 replace `REPLACE_ME` by `TTN_FP_EU868`. Following the steps in the main readme, **upload** this firmware to the KISS gadget. After uploading the code, got to **Tools->Serial Monitor**. At the bottom of the newly opened serial monitor, change the baudrate to *9600 baud*. + +Copy the 16 HEX characters following `EUI:` and use this to register a new device on The Things Network Console. + +## Register a new device +[See the TTN documentation](https://www.thethingsnetwork.org/docs/devices/registration.html). + +## SendOTAA example + +Open the SendOTAA example from **File->Examples->TheThingsNetwork->SendOTAA**. Replace the keys at the top with the keys you got from the TTN Console. After uploading this example, check the console to see if you receive any data. If you don't, you do not have TTN coverage. + +## Original Firmware + +The previous example proved that we have a working KISS gadget, a working radio module, TTN coverage, and programmed valid keys into the KISS gadget. Now we can upload the original firmware back onto the KISS gadget. Follow the steps in the readme inside the *KISSLoRa-demo_app* directory. + + +> This readme describes the steps necessary to commission a KISS gadget. Many details still need to be added, but the important steps are already included. diff --git a/README.md b/README.md index 7c965e8..69975d5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ # KISS LoRa -This repository includes example software to be used with the KISS LoRa gadget from the E&A fair. +> For common questions about the KISS gadget, see [the FAQ](faq.pdf). +> +> Voor veelgestelde vragen over de KISS gadget, zie [de FAQ](faq.pdf). + + +This repository contains example firmware to customise the KISS LoRa gadget from the E&A fair. If you do not want to customise your KISS gadget, but just want to get it to work with the original firmware, please see [the FAQ](faq.pdf) or the [Commission at Home](COMMISSION_AT_HOME.md) document. + ![alt text](KISSLoRa.png) @@ -95,7 +101,3 @@ In the Bootloader directory you will find the hex file for the bootloader that r The Schematics directory contains the electronic design of the board. It specifically shows how everything is connected. This is useful to have when writing firmware for the KISS LoRa device, to know on which pins the sensors are connected. The schematic uses the pin names and numbers from the [datasheet of the ATmega32u4](Schematics/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf). When programming this board from within Arduino IDE, we use the Arduino pin names and numbers. See the [PIN_MAPPING](Schematics/PIN_MAPPING.md) document for the translation between these pin numbers and names. - -## [Veelgestelde vragen / FAQ](faq.pdf) - -Klik op de titel om te navigeren naar de veelgestelde vragen file. From abab3d45c171c90867b6e534b1d3a150372402bd Mon Sep 17 00:00:00 2001 From: jpmeijers Date: Fri, 2 Jun 2017 17:56:05 +0200 Subject: [PATCH 7/7] Remove random sf from cayenne example. --- Examples/CayenneLPP/CayenneLPP.ino | 59 +----------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/Examples/CayenneLPP/CayenneLPP.ino b/Examples/CayenneLPP/CayenneLPP.ino index edebc41..5449694 100644 --- a/Examples/CayenneLPP/CayenneLPP.ino +++ b/Examples/CayenneLPP/CayenneLPP.ino @@ -57,9 +57,6 @@ void setup() debugSerial.println("-- JOIN"); ttn.join(appEui, appKey); - // Seed the random function - seedRandomFunction(); - //start temperature and humidity sensor sensor.begin(); } @@ -86,7 +83,7 @@ void sendData(uint8_t port) getAcceleration(&x, &y, &z); lpp.addAccelerometer(6, x, y, z); - ttn.sendBytes(lpp.getBuffer(), lpp.getSize(), 2, false, getSF()); + ttn.sendBytes(lpp.getBuffer(), lpp.getSize(), port); } uint8_t getButtonPressed() @@ -141,60 +138,6 @@ uint16_t get_lux_value() return (uint16_t)lux; //Return Lux value as value without decimal } -void seedRandomFunction() -{ - char hwEui_char_array[16+1];//16 chars + \0 - uint16_t hwEui_16_bits = 0; - - ttn.getHardwareEui(hwEui_char_array, 17); //read HWEUI from module - hwEui_16_bits = ascii_hex_to_nibble(hwEui_char_array[12]); - hwEui_16_bits |= ascii_hex_to_nibble(hwEui_char_array[13]) << 4; - hwEui_16_bits |= ascii_hex_to_nibble(hwEui_char_array[14]) << 8; - hwEui_16_bits |= ascii_hex_to_nibble(hwEui_char_array[15]) << 12; - uint16_t seed = hwEui_16_bits; - randomSeed(seed); -} - -uint8_t getSF() -{ - uint8_t txsf = 7; - uint8_t rnd = (uint8_t)random(1, 64); - - if (rnd == 1 ) { - txsf = 12; // SF12 - } - else if (rnd > 1 && rnd < 4 ) { - txsf = 11; // SF11 - } - else if (rnd > 3 && rnd < 8 ) { - txsf = 10; // SF10 - } - else if (rnd > 7 && rnd < 16 ) { - txsf = 9; // SF9 - } - else if (rnd > 15 && rnd < 32 ) { - txsf = 8; // SF8 - } - else { - txsf = 7; // SF7 - } -} - -//This function is used to convert ascii-hex string to integer -static uint8_t ascii_hex_to_nibble(char ascii_hex) -{ - uint8_t return_value=0; - - if((ascii_hex >= 'A') && (ascii_hex <= 'F')) - { - return_value |= (ascii_hex - ('A' - 10)); - } - else if((ascii_hex >= '0') && (ascii_hex <= '9')) - { - return_value |= (ascii_hex - '0'); - } - return return_value; -} //Write one register to the acceleromter void writeAccelerometer(unsigned char REG_ADDRESS, unsigned char DATA) {