WHAT A BEAUTIFUL ACCIDENT

WHAT A BEAUTIFUL ACCIDENT

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rosalindfdt/huzzahbadge.git/'


added arduino source code;

added arduino source code;

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bbolgradov/arduino-laser.git/'


Swap from green to blue

Swap from green to blue

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mcrosson/arduino_safe_lighting.git/'


Create LCD-barometer.ino

Create LCD-barometer.ino

error: pathspec 'ESP8266-code/LCD-barometer.ino' did not match any file(s) known to git

--- ESP8266-code/LCD-barometer.ino
+++ ESP8266-code/LCD-barometer.ino
@@ -0,0 +1,198 @@
+#include <Wire.h>
+#include <LiquidCrystal_I2C.h>
+#include <SPI.h>
+#include <math.h>
+#include <Adafruit_Sensor.h>
+#include <Adafruit_BMP280.h>
+#undef BMP280_ADDRESS         // Undef BMP280_ADDRESS from the BMP280 library to easily override I2C address
+#define BMP280_ADDRESS (0x76) // Low = 0x76 , High = 0x77 (default on adafruit and sparkfun BME280 modules, default for library)
+
+// display
+LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
+
+//  custom characters
+
+byte downright[8] = {
+  B00000,
+  B10000,
+  B01000,
+  B00101,
+  B00011,
+  B00111,
+  B00000,
+  B00000
+};
+
+byte upright[8] = {
+  B00000,
+  B00111,
+  B00011,
+  B00101,
+  B01000,
+  B10000,
+  B00000
+};
+
+byte backslash[8] = {
+  B00000,
+  B10000,
+  B01000,
+  B00100,
+  B00010,
+  B00001,
+  B00000,
+  B00000,
+};
+byte slopedown[8] = {
+  B00000,
+  B00000,
+  B11000,
+  B00100,
+  B00011,
+  B00000,
+  B00000,
+  B00000
+};
+
+byte slopeup[8] = {
+  B00000,
+  B00000,
+  B00011,
+  B00100,
+  B11000,
+  B00000,
+  B00000,
+  B00000
+};
+byte uparrow[8] = {
+  B00100,
+  B01110,
+  B10101,
+  B00100,
+  B00100,
+  B00100,
+  B00000,
+  B00000
+};
+
+byte downarrow[8] = {
+  B00100,
+  B00100,
+  B00100,
+  B10101,
+  B01110,
+  B00100,
+  B00000,
+  B00000
+};
+
+// barometer
+Adafruit_BMP280 bmp; // I2C
+int elevation = 60;  // height of station in m
+
+// baro queue
+float scale  = 10.0;
+int period = 24*60;
+int interval = 5;
+int entries = period / interval;
+
+// queue - to be class
+int qmax = entries;
+int qi=0;
+int q[1000];
+
+void setup()
+{
+  Serial.begin(9600);
+// display setup
+  lcd.begin(16,2);         // initialize the lcd for 16 chars 2 lines and turn on backlight
+  lcd.createChar(0, slopeup);
+  lcd.createChar(1, slopedown);
+  lcd.createChar(2, upright);
+  lcd.createChar(3, downright);
+  lcd.createChar(4, uparrow);
+  lcd.createChar(5, downarrow);
+  lcd.createChar(6, backslash);
+
+// BMP280 setup
+  Serial.println(F("BMP280 test"));
+  if (!bmp.begin()) {
+    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
+    while (1);
+  }
+  delay(5000); //let BMP settle
+// q setup;
+   qinit(0);
+   Serial.println(entries);
+}/*--(end setup )---*/
+
+void loop()
+{  lcd.clear();
+   float temp = bmp.readTemperature();
+   lcd.setCursor(0,0);
+   lcd.print(temp);
+   lcd.print(" C ");
+   lcd.setCursor(0,1);
+
+   float pressure= bmp.readPressure()/ 100.0F;
+   float slpressure = pressure + elevation/9.2F;
+   float past3 = bget(180);
+   float trend = slpressure - past3;
+   lcd.print(slpressure);
+
+// store this reading
+   bput(slpressure);
+
+   printgraph(3*60, 8);
+   delay(interval * 60 * 1000);
+}
+
+void bput(float baro) {
+   qput((int)round(baro*scale));
+}
+
+float bget(int t) {
+   int k = t / interval;
+   float val = qget(k)/scale;
+   return val;
+}
+
+void qinit(int val) {
+    for (int i=0; i < qmax;i++)
+       q[i] = val;
+}
+void qput(int val) {
+    q[qi]=val;
+    qi = (qi + 1) % qmax;
+}
+int qget(int i) {
+    int j = (qi-i-1+qmax)% qmax;
+    return q[j];
+}
+
+byte trendaschar(float trend) {
+  byte d;
+  if (trend <=-4.5) d=byte(5); else     // down arrow
+  if (trend <=-3.0) d=byte(3); else     // down right
+  if (trend <=-1.5) d=byte(6); else     // backslash
+  if (trend <-0.2)  d=byte(1); else     // slopedown
+  if (trend <=0.2)  d=0x2D; else        // dash
+  if (trend <1.5)   d=byte(0); else     // slope up
+  if (trend <3.0)   d=0x2F; else        // slash
+  if (trend <4.5)   d=byte(2); else     // upright
+  d=byte(4);                            // uparrow
+  return d;
+}
+
+void printgraph(int period, int points) {
+   int k = points - 1;
+   for (int i =k;i>0;i--) {
+     float a = bget((i-1)*period);
+     float b = bget(i*period);
+     if (a > 0 && b > 0) {  // both are actual readings
+       float trend = a - b;
+       lcd.write(trendaschar(trend));
+     }
+     else lcd.print(" ");
+   }
+}


Weather station now with exerimental sensor and indicator LEDS.

error: pathspec 'MainWeather_07/MainWeather_07.ino' did not match any file(s) known to git

--- MainWeather_07/MainWeather_07.ino
+++ MainWeather_07/MainWeather_07.ino
@@ -0,0 +1,663 @@
+/*
+ Oregon Scientific Weather Station and Manchester Decoding, (reading by delay rather than interrupt)
+ Rob Ward 2015
+ This example code is in the public domain.
+ Use at your own risk, I will take no responsibility for any loss whatsoever for its deployment.
+ Visit https://github.com/robwlakes/ArduinoWeatherOS for the latest version and
+ documentation. Filename: MainWeather_02.ino
+
+ Main_Weather, 10 July 2016  (works with Python Version 30)
+
+ The aim of this version is use the new Manchester decoding routine and incorporate detection
+ of a Oregon compatible sensor built to cover novel environmental sensors.
+ For example we could have remote temperature sampling, bat detectors, lightning detectors,
+ solar power detectors, and earthquake detectors, all reporting back to the WWW server.
+ The advantage is that by using the Oregon Scientific Protocol a person can incorporate
+ their excellent weather sensors into the overall design and largely keep the Arduino Rx software
+ design relatively simple, ie also use their Manchester implementation for our own sensors.
+
+ It may seem this program is encouraging people to build their own replacements for the
+ Oregon Scientific sensors, however it is quite the reverse.  The program is designed
+ encourage people to purchase the Oregon gear to get the basic wind, temperature, rain
+ and humidity sensors and then extend the range with original designs as suggested above.
+ If the Oregon sensors are not used, then it does not make sense to use their protocol,
+ and any RF other protocol could be as good, or maybe even better in some circumstances.
+
+ Before I discovered the Oregon products, and designed a receiver for it, I was seriously
+ considering building my own basic weather sensors. Now I am glad I did not try as the
+ quality and price of the Oregon sensors are a very good economic and reliable alternative.
+
+ Have we made the Oregon base station with the LCD redundant?  Well no, not at all. I have
+ it in the kitchen and it used by members of the family from day to day and does not take
+ anything extra to have it performing a useful monitoring job as well.  However if you want to
+ build a system that uses weather data, and combines that with other sensors, and then performs
+ other tasks such as switching pumps, or moving blinds then adding an Arduino based 433MHz Rx
+ makes an incredibly versatile platform to work with.
+
+ Have we made the Oregon USB to PC models redundant?  Again no, unless you want to take a long time
+ writing your own logging and graphing routines.  This program does not even begin to replace
+ that level of functionality.
+
+ Have we made the Anywhere OS Internet connection system redundant? Finally, again no!
+ This simple Arduino system does not report live to the internet and it would also take a lot
+ of effort to even go close to include the features of the OS internet connection system.
+
+ I would encourage anyone looking for a weather sensor based project to consider the Oregon
+ Scientific products as they produce a wide range of economically priced but solidly built
+ weather sensors.  The mechanical engineering is very good and hard to replicate by the "Geek
+ in the Street".  However the scope to extend the usefulness of this data in our designs, by
+ combining it with our own sensors (eg soil moisture, or dew point sensors) is truly amazing.
+
+ Have a look here: http://www.oregonscientificstore.com/
+
+ So get some OS gear, an Arduino and get into it :-)
+
+ NB: This program only works with Protocol 3.0 sensors.
+
+ Reference Material:
+ Thanks to these authors, they all helped in some way, especially the last one Brian!!!!
+ http://wmrx00.sourceforge.net/Arduino/OregonScientific-RF-Protocols.pdf (1)
+ http://jeelabs.net/projects/cafe/wiki/Decoding_the_Oregon_Scientific_V2_protocol (2)
+ https://github.com/phardy/WeatherStation (3)
+ http://lucsmall.com/2012/04/27/weather-station-hacking-part-1/ (4)
+ http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/ (5)
+ http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/ (6)
+ http://www.mattlary.com/2012/06/23/weather-station-project/(7)
+ https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino (8)
+ http://www.lostbyte.com/Arduino-OSV3/ (9) brian@lostbyte.com
+
+ Most of all thanks to Oregon Scientific, who have produced an affordable, high quality product.
+ I can now have my LCD Home Base in the kitchen to enjoy, with the Arduino in the garage also
+ capturing data for WWW Weather pages.  Lovely!!!!  http://www.oregonscientific.com
+ Very Highly recommended equipment. Rob Ward
+
+ Adenda:
+ The Solar Power sensor (a silicon cell's open voltage under sunlight) has been added
+ A lightning strike detector has been added with nos of strikes per 45 seconds
+ A UV Light intensity has also been added to give a relative UV light warning.
+ */
+
+#include "DHT.h"
+#include <Wire.h>
+#include <Adafruit_BMP085.h>
+
+#define DHTTYPE DHT22        // DHT 22  (AM2302)
+#define DHTPIN 2             // what pin we're connected to
+
+Adafruit_BMP085 bmp;
+DHT dht(DHTPIN, DHTTYPE);
+
+//Interface Definitions
+int     RxPin      = 8;     //The number of signal from the Rx
+int     ledPin     = 13;    //The number of the onboard LED pin
+int     RedPin     = 7;     //The Red LED, turn on for a valid Temp sensor packet
+int     GrePin     = 6;     //The Green LED, turn on for a valid Wind sensor packet
+int     BluPin     = 5;     //The Blue LED, turn on for a valid Rain sensor packet
+
+// Variables for Manchester Receiver Logic:
+word    sDelay     = 250;    //Small Delay about 1/4 of bit duration  try like 250 to 500
+word    lDelay     = 500;    //Long Delay about 1/2 of bit duration  try like 500 to 1000, 1/4 + 1/2 = 3/4
+byte    polarity   = 1;      //0 for lo->hi==1 or 1 for hi->lo==1 for Polarity, sets tempBit at start
+byte    tempBit    = 1;      //Reflects the required transition polarity
+byte    discards   = 0;      //how many leading "bits" need to be dumped, usually just a zero if anything eg discards=1
+byte    discNos    = 0;      //Counter for the Discards
+boolean firstZero  = false;  //has it processed the first zero yet?  This a "sync" bit.
+boolean noErrors   = true;   //flags if signal does not follow Manchester conventions
+//variables for Header detection
+byte    headerBits = 15;     //The number of ones expected to make a valid header
+byte    headerHits = 0;      //Counts the number of "1"s to determine a header
+//Variables for Byte storage
+byte    dataByte   = 0;      //Accumulates the bit information
+byte    nosBits    = 0;      //Counts to 8 bits within a dataByte
+byte    maxBytes   = 9;      //Set the bytes collected after each header. NB if set too high, any end noise will cause an error
+byte    nosBytes   = 0;      //Counter stays within 0 -> maxBytes
+//Bank array for packet (at least one will be needed)
+byte    manchester[12];      //Stores manchester pattern decoded on the fly
+//Oregon bit pattern, causes nibble rotation to the right, ABCDabcd becomes DCBAdcba
+byte    oregon[]   = {
+  16, 32, 64, 128, 1, 2, 4, 8
+};
+byte    csIndex       = 0;   //counter for nibbles needed for checksum
+//Weather Variables
+byte    quadrant      = 0;   //used to look up 16 positions around the compass rose
+double  avWindspeed   = 0.0;
+double  gustWindspeed = 0.0; //now used for general anemometer readings rather than avWindspeed
+float   rainTotal     = 0.0;
+float   rainRate      = 0.0;
+double  temperature   = 0.0;
+int     humidity      = 0;
+double  intTemp       = 0;
+double  intHumi       = 0;
+double  intPres       = 0 ;
+byte    intSolar      = 0;   //eg Solar power
+byte    intLightning  = 0;   //eg Lightning Strikes
+byte    intUV         = 0;   //eg UV Light Levels
+const char windDir[16][4] = {
+  "N  ", "NNE", "NE ", "ENE",  "E  ", "ESE", "SE ", "SSE",  "S  ", "SSW", "SW ", "WSW",  "W  ", "WNW", "NW ", "NNW"
+};
+
+byte    scan      = 0; // &7!=0 means that all three sensors has been detected, so it reports all three with meaningful figures first up (not the latest addition though)
+byte  seconds     = 0; // Counter to trigger the 60 seconds worth of data.
+byte  batStat     = 0; // bit1= temp, bit2=wind bit3=rain, bit4=exp if true then that sensor has not been logged for 20 minutes, its battery probably getting flat
+byte  logTemp     = 0; // Counter for number of minutes a sensor reading is missed
+byte  logWind     = 0; // Counter for number of minutes a sensor reading is missed
+byte  logRain     = 0; // Counter for number of minutes a sensor reading is missed
+byte  logExp      = 0; // Counter for number of minutes a sensor reading is missed
+int   aday        = 0; // Counts the number of minutes in a day and clears battery status every 24hrs
+
+void setup() {
+  Serial.begin(115200);
+  pinMode(RxPin, INPUT);
+  pinMode(ledPin, OUTPUT);
+  //Strobe colours in to indicate a reboot, TriColour LED is Common Anode, so requires active low to trigger.
+  pinMode(RedPin, OUTPUT);
+  pinMode(GrePin, OUTPUT);
+  pinMode(BluPin, OUTPUT);
+  //make the RGB LED flash a signature heartbeat on start up
+  digitalWrite(RedPin, 1);
+  digitalWrite(GrePin, 0);
+  digitalWrite(BluPin, 0);  //Flash Cyan
+  delay(1000);
+  digitalWrite(RedPin, 0);
+  digitalWrite(GrePin, 0);  //Flash Yellow
+  digitalWrite(BluPin, 1);
+  delay(1000);
+  digitalWrite(RedPin, 0);
+  digitalWrite(GrePin, 1);
+  digitalWrite(BluPin, 0);  //Flash Purple
+  delay(1000);
+  digitalWrite(BluPin, 1);  //all off
+  digitalWrite(RedPin, 1);
+  delay(1000);
+
+  /*  Enable these if attempting to debug the program or the circuit
+  Serial.println("Debug Manchester Version 18");
+  Serial.print("Using a delay of 1/4 bitWaveform ");
+  Serial.print(sDelay,DEC);
+  Serial.print(" uSecs 1/2 bitWaveform ");
+  Serial.print(lDelay,DEC);
+  Serial.println(" uSecs ");
+  if (polarity){
+    Serial.println("Negative Polarity hi->lo=1");
+  }
+  else{
+    Serial.println("Positive Polarity lo->hi=1");
+  }
+  Serial.print(headerBits,DEC);
+  Serial.println(" bits expected for a valid header");
+  if (discards){
+    Serial.print(discards,DEC);
+    Serial.println(" leading bits discarded from Packet");
+  }
+  else{
+    Serial.println("All bits inside the Packet");
+  }
+  Serial.println("D 00 00001111 01 22223333 02 44445555 03 66667777 04 88889999 05 AAAABBBB 06 CCCCDDDD 07 EEEEFFFF 08 00001111 09 22223333 0A 44445555");
+  */
+
+  //Tutorial on using the BMP05 Press/Temp transducer https://www.sparkfun.com/tutorials/253
+  bmp.begin();    //start the barometer and temp packages
+
+  // Initialize Timer1 for a 1 second interrupt
+  // Thanks to http://www.engblaze.com/ for this section, see their Interrupt Tutorial
+  cli();          // disable global interrupts
+  TCCR1A = 0;     // set entire TCCR1A register to 0
+  TCCR1B = 0;     // same for TCCR1B
+  // set compare match register to desired timer count:
+  OCR1A = 15624;
+  // turn on CTC mode:
+  TCCR1B |= (1 << WGM12);
+  // Set CS10 and CS12 bits for 1024 prescaler:
+  TCCR1B |= (1 << CS10);
+  TCCR1B |= (1 << CS12);
+  // enable timer compare interrupt:
+  TIMSK1 |= (1 << OCIE1A);
+  // enable global interrupts:
+  sei();
+}
+
+//Routine Driven by Interrupt, trap 1 second interrupts, and output every minute
+ISR(TIMER1_COMPA_vect) {
+  seconds++;
+  if (seconds == 60) { //make 60 for each output
+    seconds = 0;
+    //Serial.print("One second ...");
+    usbData();//comment this out to temporarily disable data every minute for debug
+  }
+} //end of interrupt routine
+
+// Main routines, find header, then sync in with it, get a packet, and decode data in it, plus report any errors.
+void loop() {
+  tempBit = polarity ^ 1;
+  noErrors = true;
+  firstZero = false;
+  headerHits = 0;
+  nosBits = 0;
+  maxBytes = 15; //too big for any known OS signal
+  nosBytes = 0;
+  discNos = discards;
+  manchester[0] = 0;
+  digitalWrite(ledPin, 0);
+  while (noErrors && (nosBytes < maxBytes)) {
+    while (digitalRead(RxPin) != tempBit) {
+    }
+    delayMicroseconds(sDelay);
+    if (digitalRead(RxPin) != tempBit) {
+      noErrors = false;
+    }
+    else {
+      byte bitState = tempBit ^ polarity;
+      delayMicroseconds(lDelay);
+      if (digitalRead(RxPin) == tempBit) {
+        tempBit = tempBit ^ 1;
+      }
+      if (bitState == 1) {
+        if (!firstZero) {
+          headerHits++;
+          if (headerHits == headerBits) {
+            //digitalWrite(ledPin,1);
+          }
+        }
+        else {
+          add(bitState);
+        }
+      }
+      else {
+        if (headerHits < headerBits) {
+          noErrors = false;
+        }
+        else {
+          if ((!firstZero) && (headerHits >= headerBits)) {
+            firstZero = true;
+            //digitalWrite(ledPin,1);
+
+          }
+          add(bitState);
+        }
+      }
+    }
+  }
+  digitalWrite(ledPin, 0);
+}
+
+void add(byte bitData) {
+  if (discNos > 0) {
+    discNos--;//discard bits before real data
+  }
+  else {
+    //the incoming bitstream has bytes placed in reversed nibble order on the fly, then the CS is done.
+    if (bitData) {
+      //if it is a '1' OR it in, others leave at a '0'
+      manchester[nosBytes] |= oregon[nosBits];//places the reversed low nibble, with hi nibble, on the fly!!!
+    }
+    //Oregon Scientific sensors have specific packet lengths
+    //Maximum bytes for each sensor must set once the sensor has been detected.
+    if (manchester[0] == 0xA2) {
+      maxBytes = 11; //rain
+      csIndex = 19;
+    }
+    if (manchester[0] == 0xA1) {
+      maxBytes = 10; //wind
+      csIndex = 18;
+    }
+    if (manchester[0] == 0xAF) {
+      maxBytes = 9; //temp
+      csIndex = 16;
+    }
+    if (manchester[0] == 0xA3) {
+      maxBytes = 10; //experimental, Solar,Strikes,UV
+      csIndex = 18; //CS byte begins at 18 nibble
+    }
+    nosBits++;
+    //Pack the bits into 8bit bytes
+    if (nosBits == 8) {
+      nosBits = 0;
+      nosBytes++;
+      manchester[nosBytes] = 0; //next byte to 0 to accumulate data
+    }
+    //Check the bytes for a valid packet once maxBytes received
+    if (nosBytes == maxBytes) {
+      //hexBinDump();
+      digitalWrite(ledPin, 1);
+      //Check Checksum first
+      if (ValidCS(csIndex)) {
+        //Process the byte array into Human readable numbers
+        analyseData();
+      }
+      noErrors = false; //make it begin again from the start
+    }
+  }
+}
+
+//Useful to invoke to debug the byte Array
+void hexBinDump() {
+  //Serial.println("T A3 10100011 07 00000111 02 00000010 AA 10101010 F0 11110000 06 00000110 FF 11111111 07 00000111 33 00110011 60 01100000");
+  Serial.print("D ");
+  for ( int i = 0; i < maxBytes; i++) {
+    byte mask = B10000000;
+    if (manchester[i] < 16) {
+      Serial.print("0");
+    }
+    Serial.print(manchester[i], HEX);
+    Serial.print(" ");
+    for (int k = 0; k < 8; k++) {
+      if (manchester[i] & mask) {
+        Serial.print("1");
+      }
+      else {
+        Serial.print("0");
+      }
+      mask = mask >> 1;
+    }
+    Serial.print(" ");
+  }
+  Serial.println();
+}
+
+//Support Routines for Nybbles and CheckSum
+
+// http://www.lostbyte.com/Arduino-OSV3/ (9) brian@lostbyte.com
+// Directly lifted, then modified from Brian's work. Now nybble's bits are pre-processed into standard order, ie MSNybble + LSNybble
+// CS = the sum of nybbles, 1 to (CSpos-1), then compared to CSpos nybble (LSNybble) and CSpos+1 nybble (MSNybble);
+// This sums the nybbles in the packet and creates a 1 byte number, and this is compared to the two nybbles beginning at CSpos
+// Note that Temp 9 bytes and anemometer 10 bytes, but rainfall uses 11 bytes per packet. (NB Rainfall CS spans a byte boundary)
+bool ValidCS(int CSPos) {
+  boolean ok = false;
+  byte cs = 0;
+  for (int x = 1; x < CSPos; x++) {
+    byte test = nyb(x);
+    cs += test;
+  }
+  //do it by nybbles as some CS's cross the byte boundaries eg rainfall
+  byte check1 = nyb(CSPos);
+  byte check2 = nyb(CSPos + 1);
+  byte check = (check2 << 4) + check1;
+  /*
+  if (manchester[0]==0xA2){
+  Serial.print(check1,HEX);  //dump out the LSNybble Checksum
+   Serial.print("(LSB), ");
+   Serial.print(check2,HEX);  //dump out the MSNybble Checksum
+   Serial.print("(MSB), ");
+   Serial.print(check,HEX);   //dump out the Rx'ed predicted byte Checksum
+   Serial.print("(combined), calculated = ");
+   Serial.println(cs,HEX);    //dump out the calculated byte Checksum
+   //Serial.print("   ");     //Space it out for the next printout
+  }
+  */
+  if (cs == check) {
+    ok = true;
+  }
+  return ok;
+}
+// Get a nybble from manchester bytes, short name so equations elsewhere are neater :-)
+// Enables the byte array to be indexed as an array of nybbles
+byte nyb(int nybble) {
+  int bite = nybble / 2;       //DIV 2, find the byte
+  int nybb  = nybble % 2;      //MOD 2  0=MSB 1=LSB
+  byte b = manchester[bite];
+  if (nybb == 0) {
+    b = (byte)((byte)(b) >> 4);
+  }
+  else {
+    b = (byte)((byte)(b) & (byte)(0xf));
+  }
+  return b;
+}
+
+//enable debug dumps if formatted data required
+void analyseData() {
+  if (manchester[0] == 0xaf) { //detected the Thermometer and Hygrometer (every 53seconds)
+    scan = scan | 1;
+    logTemp = 0; //reset missing reads to zero
+    thermom();
+    //dumpThermom();
+    digitalWrite(RedPin, 0);     //Temperature is Red
+    digitalWrite(GrePin, 1);
+    digitalWrite(BluPin, 1);
+
+  }
+  if (manchester[0] == 0xa1) { //detected the Anemometer and Wind Direction (every 14seconds)
+    scan = scan | 2;
+    logWind = 0;//reset missing reads to zero
+    anemom();
+    //dumpAnemom();
+    digitalWrite(RedPin, 1);
+    digitalWrite(GrePin, 0);    //Wind is Green
+    digitalWrite(BluPin, 1);
+  }
+  if (manchester[0] == 0xa2) { //detected the Rain Gauge (every 47seconds)
+    scan = scan | 4;
+    logRain = 0;//reset missing reads to zero
+    rain();
+    //dumpRain();
+    digitalWrite(RedPin, 1);
+    digitalWrite(GrePin, 1);
+    digitalWrite(BluPin, 0);   //Rain is Blue
+  }
+  if (manchester[0] == 0xa3) { //detected an original Sensor designed by Us every 45 seconds!!!
+    //totally experimental
+    scan = scan | 8;
+    logExp=0;//reset missing reads to zero
+    totExp();
+    //dumpExp();
+    //This code is not used by the three sensors in the WMR86 product. It may clash with other
+    //other OS Sensors and a different value chosen in the Tx and then Rx
+    digitalWrite(RedPin, 0);
+    digitalWrite(GrePin, 1);
+    digitalWrite(BluPin, 0); //Experimental is Purple!!! or Magenta???
+
+  }
+  //Serial.println(scan,DEC);
+
+}
+
+//Calculation Routines
+/*The following bit has been identified by Xander Zimmerman as a 'battery low' indicator
+  He used a variable voltage power supply to test signals from rainfall, temp/hum and anemometer eg
+  - no more messages: < 2.1 V
+  - switch to low < 2.6 V
+  - only 1 Bit used: Byte 4; Bit 6: high => Bat low (Nyb8, Bit 2)
+  This aligns with the nybble I suspected contained the Battery level indicator
+  However it does not tally with my experiments.  However I used resistors to lower the voltage to the sensor,
+  rather than a precise and steady voltage.  I am inclined to accept Xander's opinion here but reluctant
+  to change my present strategy of notification if the sensor is not detected at all for 20 minutes.
+  This strategy allows for instant collapse of the sensor whether it be low batteries, or the cold, or phyiscal damage
+  or the transmitter suddenly being shielded or a lightning strike or any other quick demise.  The Oregon LCD base console
+  does not have icons that signal a low battery, or the absence of a signal.  So if the "low battery" transmissions are
+  missed then the sensor can drop out before action is taken.
+  In the case of some batteries, I have them go "low" overnight when it has been very cold only to act normal again the next
+  day as the air temperature rose.  Some sort of flag system in the server code would need to capture and reain that status.
+  However I am sure if you see value in using the "battery low" bit, then it will be easy enough to incorporate.
+  Xander is also a fan of http://www.openhab.org/ for organising his home systems and also https://github.com/wfrog/wfrog
+  for rendering the Oregon information into graphs etc.
+*/
+
+/*   PCR800 Rain Gauge  Sample Data:
+ //  0        1        2        3        4        5        6        7        8        9        A
+ //  A2       91       40       50       93       39       33       31       10       08       02
+ //  0   1    2   3    4   5    6   7    8   9    A   B    C   D    E   F    0   1    2   3    4   5
+ //  10100010 10010001 01000000 01010000 10010011 00111001 00110011 00110001 00010000 00001000 00000010
+ //  -------- -------  bbbb---  RRRRRRRR 88889999 AAAABBBB CCCCDDDD EEEEFFFF 00001111 2222CCCC cccc
+
+ // byte(0)_byte(1) = Sensor ID?????
+ // bbbb = Battery indicator??? (7)  My investigations on the anemometer would disagree here. (However check above for Xander's contribution).
+ // After exhaustive low battery tests these bbbb bits did not change
+ // RRRRRRRR = Rolling Code Byte
+ // 222211110000.FFFFEEEEDDDD = Total Rain Fall (inches)
+ // CCCCBBBB.AAAA99998888 = Current Rain Rate (inches per hour)
+ // ccccCCCC = 1 byte Checksum cf. sum of nybbles
+ // Message length is 20 nybbles so working in inches
+ Three tips caused the following
+ 1 tip=0.04 inches or 1.1mm (observed off the LCD)
+ My experiment
+ Personally I don't like this value. I think mult by 25 and divide by 1000 IS closer to return mm directly.
+ 0.127mm per tip??? It looks close the above. Again can't vouch 100% for this, any rigorous assistance would be appreciated.
+ Over the last 6 months this has proved to be Ok
+ */
+void rain() {
+  rainTotal = float(((nyb(18) * 100000) + (nyb(17) * 10000) + (nyb(16) * 1000) + (nyb(15) * 100) + (nyb(14) * 10) + nyb(13)) * 25) / 1000.0;
+  //Serial.println((nyb(18)*100000)+(nyb(17)*10000)+(nyb(16)*1000)+(nyb(15)*100)+(nyb(14)*10)+nyb(13),DEC);
+  rainRate = float(((nyb(8) * 10000) + (nyb(9) * 1000) + (nyb(10) * 100) + (nyb(11) * 10) + nyb(12)) * 25) / 1000.0;
+  //Serial.println((nyb(8)*10000)+(nyb(9)*1000)+(nyb(10)*100)+(nyb(11)*10)+nyb(12),DEC);
+}
+void dumpRain() {
+  Serial.print("Total Rain ");
+  Serial.print(rainTotal);
+  Serial.print(" mm, ");
+  Serial.print("Rain Rate ");
+  Serial.print(rainRate);
+  Serial.println(" mm/hr ");
+}
+
+// WGR800 Wind speed sensor
+// Sample Data:
+// 0        1        2        3        4        5        6        7        8        9
+// A1       98       40       8E       00       0C       70       04       00       34
+// 0   1    2   3    4   5    6   7    8   9    A   B    C   D    E   F    0   1    2   3
+// 10100001 10011000 01000000 10001110 00000000 00001100 01110000 00000100 00000000 00110100
+// -------- -------- bbbb---- NRRRRRRR xxxx9999 xxxxxxxx CCCCDDDD xxxxFFFF 0000---- CCCCcccc
+// Av Speed 0.4000000000m/s Gusts 0.7000000000m/s  Direction: N
+
+// byte(0)_byte(1) = Sensor ID?????
+// bbbb = Battery indicator??? (7)  My investigations would disagree here.  After exhaustive low battery tests these bits did not change
+// NRRRRRRR = Rolling Code Byte, the N bit is set to 1 for 64 cycles to indicate it is reset or new to the Rx box
+// 9999 = Direction
+// DDDD.CCCC = Gust Speed (m per sec)
+// 0000.FFFF = Avg Speed(m per sec)
+// multiply by 3600/1000 for km/hr
+// ccccCCCC = 1 byte checksum cf. sum of nybbles
+// packet length is 20 nybbles
+
+void anemom() {
+  //D A1 98 40 8E 08 0C 60 04 00 A4
+  avWindspeed = ((nyb(16) * 10) + nyb(15)) * 3.6 / 10;
+  double gust = ((nyb(13) * 10) + nyb(12)) * 3.6 / 10;
+  // after every minute, reset gustWindspeed to avWindspeed and then take the highest gust after that (approx4 readings a minute)
+  if (gust > gustWindspeed) {
+    gustWindspeed = gust;
+  }
+  quadrant = nyb(9) & 0xF;
+}
+void dumpAnemom() {
+  Serial.print("Av Speed ");
+  Serial.print(avWindspeed);
+  Serial.print(" km/hr, Gusts ");
+  Serial.print(gustWindspeed);
+  Serial.print(" km/hr, Direction: ");
+  Serial.print(quadrant);
+  Serial.print(" -> ");
+  Serial.println(windDir[quadrant]);
+}
+
+// THGN800 Temperature and Humidity Sensor
+// 0        1        2        3        4        5        6        7        8        9          Bytes
+// 0   1    2   3    4   5    6   7    8   9    A   B    C   D    E   F    0   1    2   3      nybbles
+// 01011111 00010100 01000001 01000000 10001100 10000000 00001100 10100000 10110100 01111001   Bits
+// -------- -------- bbbbcccc RRRRRRRR 88889999 AAAABBBB SSSSDDDD EEEE---- CCCCcccc --------   Explanation
+// byte(0)_byte(1) = Sensor ID?????
+// bbbb = Battery indicator??? (7), My investigations on the anemometer would disagree here.  After exhaustive low battery tests these bits did not change
+// RRRRRRRR = Rolling code byte
+// nybble(5) is channel selector c (Switch on the sensor to allocate it a number)
+// BBBBAAAA.99998888 Temperature in BCD
+// SSSS sign for negative (- is !=0)
+// EEEEDDDD Humidity in BCD
+// ccccCCCC 1 byte checksum cf. sum of nybbles
+// Packet length is 18 nybbles and indeterminate after that
+// H 00 01 02 03 04 05 06 07 08 09    Byte Sequence
+// D AF 82 41 CB 89 42 00 48 85 55    Real example
+// Temperature 24.9799995422 degC Humidity 40.0000000000 % rel
+void thermom() {
+  temperature = (double)((nyb(11) * 100) + (nyb(10) * 10) + nyb(9)) / 10; //accuracy to 0.1 degree seems unlikely
+  if (nyb(12) == 1) { //  Trigger a negative temperature
+    temperature = -1.0 * temperature;
+  }
+  humidity = (nyb(14) * 10) + nyb(13);
+}
+void dumpThermom() {
+  Serial.print("Temperature ");
+  Serial.print(temperature);
+  Serial.print(" degC, Humidity ");
+  Serial.print(humidity);
+  Serial.println("% Rel");
+}
+//The novel added extra sensors, extracting and applying any necessary conversions
+void totExp() {
+  //No complicated conversions required here
+  intSolar = byte(manchester[2]);     //EG To apply a Solar Cell to the input?
+  intLightning = byte(manchester[3]); //EG Lightning Strikes
+  intUV = byte(manchester[4]);        //Eg UV Light Levels
+}
+
+void dumpExp() {
+  Serial.print("Solar Power =");
+  Serial.println(intSolar, DEC);
+  Serial.print("Lightning Strikes =");
+  Serial.println(intLightning, DEC);
+  Serial.print("Light Intensity");
+  Serial.print(intUV, DEC);
+}
+
+// Formating routine for interface to host computer, output once a minute once all three sesnors have been detected
+void usbData() {
+  // Stn Id, Packet Type, Wind Quadrant, Wind Speed, Rain Tips, Ext temp, Int Temp, Int Pressure, Int Humidity
+  intHumi = (double)dht.readHumidity();      //DHT22 readings %Humidity
+  intTemp = (double)bmp.readTemperature();   //internal temperature
+  intPres = (double)bmp.readPressure() / 100.0; //Pa reduced to mBar
+  //leave this check at 7 until the other readings are stabilized
+  if ((scan&7)==7) {               //scan==15 means all 4 readings now have a valid value, ready for output on Serial
+    //Battery/Signal status, OR in the the four status values for the signal connections.
+    logTemp++;
+    if (logTemp>40){
+      batStat = batStat | 1;
+      }
+    logWind++;
+    if (logWind>40){
+      batStat = batStat | 2;
+      }
+    logRain++;
+    if (logRain>40){
+      batStat = batStat | 4;
+      }
+    logExp++;
+    if (logExp>40){
+      batStat = batStat | 8;
+      }
+    //reset the batStat to 0 every 24hours
+    aday++;
+    if (aday>1440){
+      batStat=0;
+      aday=0;
+      }
+    // Order: Battery Status, Quadrant, Wind Gust, Rainfall, Temperature, InternalTemp, Internal Pressure, Int Humidity, Solar Power, Lightning, UV Radiation
+    Serial.print(batStat,DEC);       //Send out the number to indicate if a sensor is not transmitting for maore than 20 mins. Low Battery or other damage.
+    Serial.print(",");
+    Serial.print(quadrant);          //0-15 in 22.5 degrees steps clockwise
+    Serial.print(",");
+    Serial.print(gustWindspeed, 1);  //Gust windspeed km/hr, not average windspeed (graphing over 10 samples gives Average)
+    Serial.print(",");
+    gustWindspeed = avWindspeed;     //reset gust to average, then take the larger next reading
+    Serial.print(rainTotal, 1);      //currently considered to checked for a good calibration to mm
+    Serial.print(",");
+    Serial.print(temperature, 2);    // OS Temperature Centigrade
+    Serial.print(",");
+    Serial.print(intTemp, 2);        //BMP085 temperature (used for compensation reading) Centigrade
+    Serial.print(",");
+    Serial.print(intPres, 2);        //BMP085 pressure reading milli-bars
+    Serial.print(",");
+    Serial.print(intHumi);           //Digital DHT22 seems better than the OS in Temp/Hum sensor % relative
+    Serial.print(",");
+    Serial.print(intSolar,DEC);       //A reading from experimental Solar Power sensor
+    Serial.print(",");
+    Serial.print(intLightning,DEC);       //A reading from the nos of Lightning Strikes
+    Serial.print(",");
+    Serial.print(intUV, DEC);      //UV Sensor
+    Serial.println();
+
+    //Indicate the transmission of this one second data with a white light set up R+B+G!!
+    digitalWrite(RedPin, 0);         //White, all colours on, data has been logged to the Server
+    digitalWrite(GrePin, 0);
+    digitalWrite(BluPin, 0);
+    }
+}
+
+


Added Relayduino Example

Added Relayduino Example

error: pathspec 'examples/relayduino/relayduino.ino' did not match any file(s) known to git

--- examples/relayduino/relayduino.ino
+++ examples/relayduino/relayduino.ino
@@ -0,0 +1,191 @@
+//*****************************************************************************
+//
+// relayduino.ino - Controling the Relayduino from the Cloud with Exosite
+//
+// Copyright (c) 2012 Exosite LLC.  All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+//  * Redistributions of source code must retain the above copyright notice,
+//    this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//  * Neither the name of Exosite LLC nor the names of its contributors may
+//    be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+//*****************************************************************************
+
+/******************************* USER SETTINGS *******************************/
+// Fill in your MAC here! (e.g. {0x90, 0xA2, 0xDA, 0x00, 0x22, 0x33})
+byte macData[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+//Fill in your CIK here! (https://portals.exosite.com -> Add Device)
+char cikData[] = "0000000000000000000000000000000000000000";
+
+// Set the maximum interval we should read and write to Exosite.
+unsigned long loop_interval_ms = 10000; // milliseconds
+
+/*****************************************************************************/
+
+#include <SPI.h>
+#include <Ethernet.h>
+#include <Exosite.h>
+
+// Pin Definitions
+#define ANIN1 6   // Analog 1 is connected to Arduino Analog In 6
+#define ANIN2 7   // Analog 2 is connected to Arduino Analog In 7
+#define ANIN3 0   // Analog 3 is connected to Arduino Analog In 0
+const int Analogs[3] = {ANIN1, ANIN2, ANIN3};
+const char* Analog_Aliases[3] = {"ANIN1", "ANIN2", "ANIN3"};
+
+#define REL1 2  // Relay 1 is connected to Arduino Digital 2
+#define REL2 3  // Relay 2 is connected to Arduino Digital 3 PWM
+#define REL3 4  // Relay 3 is connected to Arduino Digital 4
+#define REL4 5  // Relay 4 is connected to Arduino Digital 5 PWM
+#define REL5 6  // Relay 5 is connected to Arduino Digital 6 PWM
+#define REL6 7  // Relay 6 is connected to Arduino Digital 7
+#define REL7 8  // Relay 7 is connected to Arduino Digital 8
+#define REL8 9  // Relay 8 is connected to Arduino Digital 9 PWM
+const int Relays[8] = {REL1, REL2, REL3, REL4, REL5, REL6, REL7, REL8};
+//const int PWMAble[4] = {2, 4, 5, 8};
+const char* Relay_Aliases[8] = {"REL1", "REL2", "REL3", "REL4", "REL5", "REL6", "REL7", "REL8"};
+
+#define OI1 15 // Opto-Isolated Input 1 is connected to Arduino Analog 1 which is Digital 15
+#define OI2 16 // Opto-Isolated Input 2 is connected to Arduino Analog 2 which is Digital 16
+#define OI3 17 // Opto-Isolated Input 3 is connected to Arduino Analog 3 which is Digital 17
+#define OI4 18 // Opto-Isolated Input 4 is connected to Arduino Analog 4 which is Digital 18
+const int Optos[4] = {OI1, OI2, OI3, OI4};
+const char* Opto_Aliases[4] = {"OI1", "OI2", "OI3", "OI4"};
+
+//global variables
+
+class EthernetClient client;
+Exosite exosite(cikData, &client);
+
+unsigned long last_millis = 0;
+
+const char* readString = "REL1&REL2&REL3&REL4&REL5&REL6&REL7&REL8";
+String writeString;
+String returnString;
+String tempString;
+int index = 0;
+int lastIndex = -1;
+int pinNumber = 0;
+
+/*==============================================================================
+ * setup
+ *
+ * Arduino setup function.
+ *=============================================================================*/
+void setup()
+{
+  Serial.begin(115200);
+  Serial.println(F("Boot"));
+
+  Ethernet.begin(macData);
+  delay(1000);
+
+  for(int i = 0; i < 8; i++){
+    pinMode(Relays[i], OUTPUT);
+  }
+}
+
+/*==============================================================================
+ * loop
+ *
+ * Arduino loop function.
+ *=============================================================================*/
+void loop()
+{
+  Serial.println(F("------Loop Start------"));
+
+  writeString = "";
+  returnString = "";
+  index = 0;
+  lastIndex = -1;
+
+  // Setup Values to Write
+  for(int i = 0; i < 4; i++){
+    writeString += String(Opto_Aliases[i]) + "=" + digitalRead(Optos[i]) + "&";
+  }
+  for(int i = 0; i < 3; i++){
+    writeString += String(Analog_Aliases[i]) + "=" + analogRead(Analogs[i]) + "&";
+  }
+
+  Serial.print(F("Connecting to Exosite..."));
+
+  if(exosite.readWrite(writeString, readString, returnString)){
+    Serial.println(F("Success"));
+    for(;;){
+      index = returnString.indexOf("=", lastIndex+1);
+      if(index != 0){
+        tempString = returnString.substring(lastIndex+1, index);
+
+        pinNumber = getRelayPin(tempString);
+        if(pinNumber == 0){ //Not a Relay Pin Name
+          Serial.print(F("Unknown Alias:"));
+          Serial.println(tempString);
+          continue;
+        }
+
+        lastIndex = returnString.indexOf("&", index+1);
+
+        if(lastIndex != -1){
+          tempString = returnString.substring(index+1, lastIndex);
+        }else{
+          tempString = returnString.substring(index+1);
+        }
+
+        if(tempString == "1"){
+          digitalWrite(pinNumber, 1);
+        }else if(tempString == "0"){
+          digitalWrite(pinNumber, 0);
+        }else{
+          Serial.print(F("Unknown Setting: "));
+          Serial.println(tempString);
+        }
+
+        if(lastIndex == -1)
+          break;
+
+      }else{
+        Serial.println(F("No Index"));
+        break;
+      }
+    }
+  }else{
+    Serial.println(F("Error Communicating with Exosite"));
+  }
+
+  Serial.print("Next Loop to Start In: ");
+  Serial.print((millis() - last_millis + loop_interval_ms)/1000);
+  Serial.println(" Seconds");
+
+  while(millis() < last_millis + loop_interval_ms){
+    if(millis() < last_millis)
+      last_millis = millis(); // millis() overflowed and last_millis didn't.
+
+    //Serial.println(millis());
+  }
+
+  last_millis += loop_interval_ms; // This is an unsigned long, it should overflow just the same as millis().
+}
+
+int getRelayPin(String name){
+  for(int i = 0; i < 8; i++){
+    if(name == Relay_Aliases[i])
+      return Relays[i];
+  }
+
+  return 0;
+}


Added a method to write an address to EEProm

error: pathspec 'EEPromTools/AddressSet/AddressSet.ino' did not match any file(s) known to git

--- EEPromTools/AddressSet/AddressSet.ino
+++ EEPromTools/AddressSet/AddressSet.ino
@@ -0,0 +1,74 @@
+/*
+ * Write out an I2C address if one doesn't already exist
+ */
+#include <EEPROM.h>
+
+#define PIN_DEBUG_LED 13
+
+#define HMTL_ADDRESS_MAGIC 0x53
+#define HMTL_ADDRESS_START 0x101
+
+byte my_address = 2; // This value is written to EEPROM
+boolean wrote_address = false;
+
+void setup()
+{
+  Serial.begin(9600);
+
+  // Check if there is already an address
+  int value = EEPROM.read(HMTL_ADDRESS_START);
+  if (value != HMTL_ADDRESS_MAGIC) {
+    // No existing address, write it out
+    EEPROM.write(HMTL_ADDRESS_START, HMTL_ADDRESS_MAGIC);
+    EEPROM.write(HMTL_ADDRESS_START + 1, my_address);
+    wrote_address = true;
+  } else {
+    // Read in the pre-existing address
+    my_address = EEPROM.read(HMTL_ADDRESS_START + 1);
+  }
+
+  pinMode(PIN_DEBUG_LED, OUTPUT);
+}
+
+
+void loop()
+{
+  static long last_update = 0;
+  if (millis() - last_update > 1000) {
+    Serial.print("My address: ");
+    Serial.print(my_address);
+    Serial.print(" Was address written: ");
+    Serial.println(wrote_address);
+    last_update = millis();
+  }
+
+  blinkValue(my_address, 500, 4);
+  delay(10);
+}
+
+void blinkValue(int value, int period_ms, int idle_periods)
+{
+  static long period_start_ms = 0;
+  static long last_step_ms = 0;
+  static boolean led_value = true;
+
+  long now = millis();
+  if (period_start_ms == 0) period_start_ms = now;
+
+  if ((now - last_step_ms) > period_ms) {
+    int current_step = (now - period_start_ms) / period_ms;
+
+    if (current_step >= (value * 2 + idle_periods)) {
+      // The end of the current display cycle
+      period_start_ms = now;
+    } else if (current_step >= value * 2) {
+      return;
+    }
+
+    led_value = !led_value;
+    digitalWrite(PIN_DEBUG_LED, led_value);
+
+    last_step_ms = now;
+  }
+
+}


Adding DS18x20 sensor capability!

Adding DS18x20 sensor capability!

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/MitchellJThomas/medir.git/'


Sketch GSM

Sketch GSM

Adicionado sketch Arduino com suporte ao módulo GSM

error: pathspec 'Arduino' did not match any file(s) known to git
error: pathspec 'sketchs/gsm/gsm.ino' did not match any file(s) known to git


ficherillo

ficherillo

error: pathspec 'Ardufocuser/test/temperature_dht11_lcd_read/temperature_dht11_lcd_read.ino' did not match any file(s) known to git

--- Ardufocuser/test/temperature_dht11_lcd_read/temperature_dht11_lcd_read.ino
+++ Ardufocuser/test/temperature_dht11_lcd_read/temperature_dht11_lcd_read.ino
@@ -0,0 +1,55 @@
+#include <DHT11.h>
+#include <Wire.h>
+#include <math.h>
+#include <LiquidCrystal_I2C.h>
+
+
+#define TEMPIN 7
+
+DHT11 dht11(TEMPIN);
+LiquidCrystal_I2C lcd(0x27, 16, 2);
+
+
+unsigned long  lastTimeUpdate=100;
+float temperature;
+float humidity;
+int error;
+
+void TempController(){
+  error=dht11.read(temperature, humidity);
+  delay(DHT11_RETRY_DELAY);
+}
+
+void LCDController(){
+  lcd.clear();
+  lcd.print("TEMP ");
+  lcd.print(temperature);
+  lcd.print(" C");
+
+  lcd.setCursor(0,1);
+  lcd.print("HUM  ");
+  lcd.print(humidity);
+}
+
+
+void setup() {
+
+  Serial.begin(9600);
+  lcd.begin();
+  lcd.backlight();
+  lcd.print("RUN!");
+
+
+}
+
+void loop() {
+
+  if (millis() > lastTimeUpdate) {
+    TempController();
+    LCDController();
+    lastTimeUpdate = millis() + 100;
+  }
+}
+
+
+


added IR test, for mega, use pin 9

added IR test, for mega, use pin 9

error: pathspec 'test/IR_test/IR_test.ino' did not match any file(s) known to git

--- test/IR_test/IR_test.ino
+++ test/IR_test/IR_test.ino
@@ -0,0 +1,33 @@
+/*
+  IR test
+
+  Used to test IR functionality.
+
+  On Mega, you need to use pin 9
+
+  Created 07/25/2013
+  By benzh@eecs.berkeley.edu
+
+*/
+
+#include <IRremote.h>
+
+// An IR LED must be connected to Arduino PWM pin 3.
+// On Mega, you need to use pin 9
+IRsend irsend;
+int ledPin = 8;
+
+void setup()
+{
+  Serial.begin(9600);
+  delay(100);
+  Serial.print("system begins!");
+}
+
+void loop() {
+  delay(1000);
+  unsigned int session_id = random(0xFFFF);
+  Serial.print("[INIT] Sending IR: ");
+  Serial.println(session_id);
+  irsend.sendSony(session_id, 16);
+}


Adding DNS example sketch.

Adding DNS example sketch.

error: pathspec 'examples/Ethernet/CosaDNS/CosaDNS.ino' did not match any file(s) known to git

--- examples/Ethernet/CosaDNS/CosaDNS.ino
+++ examples/Ethernet/CosaDNS/CosaDNS.ino
@@ -0,0 +1,75 @@
+/**
+ * @file CosaDNS.ino
+ * @version 1.0
+ *
+ * @section License
+ * Copyright (C) 2014, Mikael Patel
+ *
+ * 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.
+ *
+ * @section Description
+ * W5100 Ethernet Controller device driver example code; DNS client.
+ *
+ * This file is part of the Arduino Che Cosa project.
+ */
+
+#include "Cosa/Socket/Driver/W5100.hh"
+#include "Cosa/INET.hh"
+#include "Cosa/INET/DNS.hh"
+
+#include "Cosa/Watchdog.hh"
+#include "Cosa/Trace.hh"
+#include "Cosa/IOStream/Driver/UART.hh"
+
+// Network configuration
+#define MAC 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed
+#define IP 192,168,0,100
+#define SUBNET 255,255,255,0
+#define SERVER 192,168,0,1
+// #define SERVER 79,138,0,180
+// #define SERVER 85,8,31,209
+
+// W5100 Ethernet Controller with MAC-address
+const uint8_t mac[6] PROGMEM = { MAC };
+W5100 ethernet(mac);
+
+// Query configuration
+#define NAME PSTR("www.arduino.cc")
+// #define NAME PSTR("www.google.com")
+// #define NAME PSTR("www.github.com")
+
+void setup()
+{
+  uart.begin(9600);
+  trace.begin(&uart, PSTR("CosaDNSstarted"));
+  Watchdog::begin();
+
+  uint8_t ip[4] = { IP };
+  uint8_t subnet[4] = { SUBNET };
+  ASSERT(ethernet.begin(ip, subnet));
+}
+
+void loop()
+{
+  DNS dns;
+  uint8_t server[4] = { SERVER };
+  ASSERT(dns.begin(ethernet.socket(Socket::UDP), server));
+  trace << PSTR("SERVER = ");
+  INET::print_addr(trace, server, DNS::PORT);
+
+  uint8_t host[4];
+  ASSERT(dns.gethostbyname_P(NAME, host) == 0);
+  trace << PSTR(":gethostbyname(") << NAME << PSTR(") = ");
+  INET::print_addr(trace, host);
+  trace.println();
+
+  SLEEP(10);
+}


display16ColorImage init

display16ColorImage init

sample code for 16 shade image

error: pathspec 'display16ColorImage/display16ColorImage.ino' did not match any file(s) known to git

--- display16ColorImage/display16ColorImage.ino
+++ display16ColorImage/display16ColorImage.ino
@@ -0,0 +1,60 @@
+/* This progam displays an image on a Peggy2.
+   It was automatically generated by BMP2PEG.
+
+   Copyright (c) 2009 Mark Delp.  All right reserved.
+
+   This program 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 software 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 software; if not, see http://www.gnu.org/licenses.
+*/
+
+#include <Peggy2.h>
+
+// declare bitmap data
+uint32_t einstein[4][25] = {
+{0x00164BC0, 0x000F5F48, 0x00288AE2, 0x0020FD14, 0x0045366C, 0x01619B68, 0x00159994, 0x005C1676, 0x00016AFA, 0x00C84984, 0x00159EE2, 0x0133CEBE, 0x001FE4B4, 0x00FB8BD2, 0x0191536C, 0x008F0A41, 0x015C3302, 0x0098819E, 0x00B2A528, 0x016C9578, 0x00AFFEB4, 0x0049FE50, 0x0000D6C0, 0x007E2120, 0x001D5080},
+{0x000B32C0, 0x00148960, 0x001F4960, 0x000F6530, 0x000F1C88, 0x001FE1C4, 0x005BE330, 0x0043E158, 0x00338954, 0x00739150, 0x00CEC16C, 0x00F339B8, 0x005147FC, 0x001AFA1C, 0x00926CA0, 0x00B07634, 0x00C8AFCC, 0x002DFD68, 0x0184A200, 0x01F79F80, 0x015DE080, 0x002C0400, 0x0039B980, 0x00046000, 0x00040000},
+{0x0006FC80, 0x000BF640, 0x0017F670, 0x000F8238, 0x003EE0E8, 0x003FFDA4, 0x003FFDF4, 0x003FFDB0, 0x007FF5B0, 0x003FEDB4, 0x003B3C88, 0x000C204C, 0x008C3844, 0x008CFDD4, 0x00273FE4, 0x0026FFF4, 0x0063BBFC, 0x000317C0, 0x000F5FC0, 0x00765840, 0x000F4080, 0x00179980, 0x0002E100, 0x00018000, 0x00020000},
+{0x0001FF00, 0x0007FF80, 0x000FFF80, 0x001FFFC0, 0x001FFF10, 0x001FFE18, 0x003FFE08, 0x003FFE0C, 0x003FFE0C, 0x007FFE08, 0x007FF810, 0x007E1000, 0x007E1008, 0x00773028, 0x007FF018, 0x007FF008, 0x003FF000, 0x007FE000, 0x007FE000, 0x000FE000, 0x00060040, 0x000660C0, 0x00040000, 0x00008000, 0x00000000}
+};
+
+// declare frame buffers
+Peggy2 frame1;
+Peggy2 frame2;
+Peggy2 frame3;
+Peggy2 frame4;
+
+void setup()  // run once, when the sketch starts
+{
+ // Call this once to init the hardware.
+ // (Only needed once, even if you've got lots of frames.)
+ frame1.HardwareInit();
+
+ // populate each row of each frame buffer from the bitmap data
+ int row;
+ for (row = 0; row < 25; row++)
+ {
+  frame1.WriteRow(row, einstein[0][row]);
+  frame2.WriteRow(row, einstein[1][row]);
+  frame3.WriteRow(row, einstein[2][row]);
+  frame4.WriteRow(row, einstein[3][row]);
+ }
+
+}
+
+void loop() // run over and over again
+{
+  frame1.RefreshAll(1);  // draw frame buffer 1 time
+  frame2.RefreshAll(2);  // draw frame buffer 2 times
+  frame3.RefreshAll(4);  // draw frame buffer 4 times
+  frame4.RefreshAll(8);  // draw frame buffer 8 times
+}


Added example for Arduboy hardware

Added example for Arduboy hardware

error: pathspec 'examples/arduboy_base/arduboy_base.ino' did not match any file(s) known to git

--- examples/arduboy_base/arduboy_base.ino
+++ examples/arduboy_base/arduboy_base.ino
@@ -0,0 +1,69 @@
+/*
+    MIT License
+
+    Copyright (c) 2018, Alexey Dynda
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in all
+    copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+    SOFTWARE.
+*/
+
+///////////////////////////////////////////////////////////////////////
+// This sketch will run on Arduboy HW (compile for Leonardo board)
+//////////////////////////////////////////////////////////////////////
+
+#include "ssd1306.h"
+#include "nano_engine.h"
+
+NanoEngine1 engine;
+
+NanoRect rect = { {15,12}, {60,35} }; // Lets make rect smaller than in previous example
+
+bool drawAll()
+{
+    engine.canvas.clear();
+    engine.canvas.setColor(RGB_COLOR8(255,255,0));
+    engine.canvas.drawRect(rect);   // draw rect in buffer
+    return true;
+}
+
+void setup()
+{
+    /* Init Mono OLED 128x64 for Arduboy. 6 - RESET, 12 - CS, 4 - D/C */
+    ssd1306_128x64_spi_init(6, 12, 4);
+
+    engine.begin();
+    engine.setFrameRate(45);
+    engine.drawCallback( drawAll );  // Set callback to draw parts, when NanoEngine8 asks
+    engine.connectArduboyKeys();        // Connect ADC-buttons Z-keypad to analog A0 pin
+    engine.refresh();                // Makes engine to refresh whole display content at start-up
+}
+
+void loop()
+{
+    if (!engine.nextFrame()) return;
+    NanoPoint point = {0,0};
+    if (engine.pressed( BUTTON_RIGHT )) point.x = +1;
+    if (engine.pressed( BUTTON_LEFT ))  point.x = -1;
+    if (engine.pressed( BUTTON_UP ))    point.y = -1;
+    if (engine.pressed( BUTTON_DOWN ))  point.y = +1;
+    engine.refresh(rect);            // Update screen content at old rect position
+    rect += point;                   // Move rect according to pressed keys
+    engine.refresh(rect);            // Update screen content at new rect position
+    engine.display();                // refresh display content
+}
+


added imacode:

added imacode:

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/niliur/niliur.github.io.git/'


Create Serial_for_EC_Calibration_m0.ino

Create Serial_for_EC_Calibration_m0.ino

error: pathspec 'OpenCTD_Feather_Adalogger/Serial_for_EC_Calibration_m0/Serial_for_EC_Calibration_m0.ino' did not match any file(s) known to git

--- OpenCTD_Feather_Adalogger/Serial_for_EC_Calibration_m0/Serial_for_EC_Calibration_m0.ino
+++ OpenCTD_Feather_Adalogger/Serial_for_EC_Calibration_m0/Serial_for_EC_Calibration_m0.ino
@@ -0,0 +1,26 @@
+#include <SoftwareSerial.h>
+
+SoftwareSerial gtSerial(12, 13); // Arduino RX, Arduino TX
+
+void setup() {
+  Serial.begin(9600);    // serial / USB port
+  gtSerial.begin(9600);  // software serial port
+}
+
+byte rx_byte = 0;        // stores received byte
+
+void loop() {
+  // check if byte available from USB port
+  if (Serial.available()) {
+    rx_byte = Serial.read();
+    // send a byte to the software serial port
+    gtSerial.write(rx_byte);
+  }
+
+  // check if byte available on the software serial port
+  if (gtSerial.available()) {
+    // get the byte from the software serial port
+    rx_byte = gtSerial.read();
+    Serial.write(rx_byte);
+  }
+}


Basic code to run steppers.

Basic code to run steppers.

From howtomechatronics.com A49888 Nema 17 tutorial file.

/bin/sh: 1: Syntax error: Unterminated quoted string


New poroduction stair script stairs light up white going down and white going up with blue on the edges while idle. last 6 LEDs still not lighting up...

error: pathspec 'Scripts/stair_lights_w_motion_White_PRODUCTION/stair_lights_w_motion_white_PRODUCTION.ino' did not match any file(s) known to git

--- Scripts/stair_lights_w_motion_White_PRODUCTION/stair_lights_w_motion_white_PRODUCTION.ino
+++ Scripts/stair_lights_w_motion_White_PRODUCTION/stair_lights_w_motion_white_PRODUCTION.ino
@@ -0,0 +1,191 @@
+// Edit by Serge Niko June 2015
+
+#include <Adafruit_NeoPixel.h>
+
+#define PIN 6
+
+// Parameter 1 = number of pixels in strip
+// Parameter 2 = Arduino pin number (most are valid)
+// Parameter 3 = pixel type flags, add together as needed:
+//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
+//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
+//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
+//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
+
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(447, PIN, NEO_GRB + NEO_KHZ800); // the first variable is the number of LEDs
+
+// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
+// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
+// and minimize distance between Arduino and first pixel.  Avoid connecting
+// on a live circuit...if you must, connect GND first.
+
+// Set up Variables
+ unsigned long timeOut=60000; // timestamp to remember when the PIR was triggered.
+ int downUp = 0;              // variable to rememer the direction of travel up or down the stairs
+ int alarmPinTop = 10;        // PIR at the top of the stairs
+ int alarmPinBottom =11;      // PIR at the bottom of the stairs
+ int alarmValueTop = LOW;    // Variable to hold the PIR status
+ int alarmValueBottom = LOW; // Variable to hold the PIR status
+ int ledPin = 13;           // LED on the arduino board flashes when PIR activated
+ int LDRSensor = A0;        // Light dependant resistor
+ int LDRValue = 0;          // Variable to hold the LDR value
+ int colourArray[350];      // An array to hold RGB values
+ int change = 1;            // used in 'breathing' the LED's
+ int breathe = 0;           // used in 'breathing' the LED's
+
+
+void setup() {
+   strip.begin();
+   strip.setBrightness(255); //adjust brightness here
+   strip.show(); // Initialize all pixels to 'off'
+   Serial.begin (9600);  // only requred for debugging
+   pinMode(ledPin, OUTPUT);  // initilise the onboard pin 13 LED as an indicator
+   pinMode(alarmPinTop, INPUT_PULLUP);     // for PIR at top of stairs initialise the input pin and use the internal restistor
+   pinMode(alarmPinBottom, INPUT_PULLUP);  // for PIR at bottom of stairs initialise the input pin and use the internal restistor
+   delay (200); // it takes the sensor 2 seconds to scan the area around it before it can 2000 was default
+   //detect infrared presence.
+
+}
+
+ void loop() {
+
+    if (timeOut+15700 < millis()) {        // idle state - 'breathe' the top and bottom LED to show program is looping
+       uint32_t blue = (0, 0, breathe);
+       breathe = breathe + change;
+       strip.setPixelColor(0, blue);
+       strip.setPixelColor(27, blue);
+       strip.setPixelColor(28, blue);
+       strip.setPixelColor(57, blue);
+       strip.setPixelColor(58, blue);
+       strip.setPixelColor(87, blue);
+       strip.setPixelColor(88, blue);
+       strip.setPixelColor(117, blue);
+       strip.setPixelColor(118, blue);
+       strip.setPixelColor(147, blue);
+       strip.setPixelColor(148, blue);
+       strip.setPixelColor(177, blue);
+       strip.setPixelColor(178, blue);
+       strip.setPixelColor(207, blue);
+       strip.setPixelColor(208, blue);
+       strip.setPixelColor(237, blue);
+       strip.setPixelColor(238, blue);
+       strip.setPixelColor(267, blue);
+       strip.setPixelColor(268, blue);
+       strip.setPixelColor(297, blue);
+       strip.setPixelColor(298, blue);
+       strip.setPixelColor(327, blue);
+       strip.setPixelColor(328, blue);
+       strip.setPixelColor(357, blue);
+       strip.setPixelColor(358, blue);
+       strip.setPixelColor(387, blue);
+       strip.setPixelColor(388, blue);
+       strip.setPixelColor(417, blue);
+       strip.setPixelColor(418, blue);
+       strip.setPixelColor(446, blue);
+       strip.show();
+       if (breathe == 100 || breathe == 0) change = -change;      // breathe the LED from 0 = off to 100 = fairly bright
+       if (breathe == 100 || breathe == 0); delay (100);           // Pause at beginning and end of each breath
+     delay(10);
+
+
+  }
+
+    alarmValueTop = digitalRead(alarmPinTop);    // Constantly poll the PIR at the top of the stairs
+    //Serial.println(alarmPinTop);
+    alarmValueBottom = digitalRead(alarmPinBottom);  // Constantly poll the PIR at the bottom of the stairs
+    //Serial.println(alarmPinBottom);
+
+    if (alarmValueTop == HIGH && downUp != 2)  {      // the 2nd term allows timeOut to be contantly reset if one lingers at the top of the stairs before decending but will not allow the bottom PIR to reset timeOut as you decend past it.
+      timeOut=millis();  // Timestamp when the PIR is triggered.  The LED cycle wil then start.
+      downUp = 1;
+      //clearStrip();
+      topdown();         // lights up the strip from top down
+    }
+
+    if (alarmValueBottom == HIGH && downUp != 1)  {    // the 2nd term allows timeOut to be contantly reset if one lingers at the bottom of the stairs before decending but will not allow the top PIR to reset timeOut as you decend past it.
+      timeOut=millis();    // Timestamp when the PIR is triggered.  The LED cycle wil then start.
+      downUp = 2;
+      //clearStrip();
+      bottomup();         // lights up the strip from bottom up
+    }
+
+    if (timeOut+10000 < millis() && timeOut+15000 < millis()) {    //switch off LED's in the direction of travel.
+       if (downUp == 1) {
+          colourWipeDown(strip.Color(0, 0, 0), 200); // Off
+       }
+       if (downUp == 2)  {
+        colourWipeUp(strip.Color(0, 0, 0), 200);   // Off
+       }
+      downUp = 0;
+
+    }
+
+
+
+}
+
+ void topdown() {
+    Serial.println ("detected top");                  // Helpful debug message
+    colourWipeDown(strip.Color(10, 10, 10), 300 );    // Warm White - RGB - then 4th number is delay
+    //for(int i=0; i<3; i++) {                        // Helpful debug indication flashes led on Arduino board twice
+      //digitalWrite(ledPin,HIGH);
+     // delay(1000);
+      //digitalWrite(ledPin,LOW);
+      //delay(1000);
+    //}
+ }
+
+
+
+ void bottomup() {
+    Serial.println ("detected bottom");            // Helpful debug message
+    colourWipeUp(strip.Color(10, 10, 10), 300);    // Warm White
+    //for(int i=0; i<3; i++) {                     // Helpful debug indication flashes led on Arduino board twice
+      //digitalWrite(ledPin,HIGH);
+      // delay(1000);
+      //digitalWrite(ledPin,LOW);
+      //delay(200);
+    //}
+  }
+
+ // Fade light each step strip
+ void colourWipeDown(uint32_t c, uint16_t wait) {
+
+  for (uint16_t j = 0; j < 15; j++){
+  int start = strip.numPixels()/15 *j;
+  Serial.println(j);
+
+        for (uint16_t i = start; i < start + 35; i++){
+    strip.setPixelColor(i, c);
+        }
+      strip.show();
+  delay(wait);
+  }
+
+ }
+
+
+void clearStrip(){
+  for (int l=0; l<strip.numPixels(); l++){
+    strip.setPixelColor(l, (0,0,0));
+  }
+
+}
+ // Fade light each step strip
+ void colourWipeUp(uint32_t c, uint16_t wait) {
+   for (uint16_t j = 15; j > 0; j--){
+   int start = strip.numPixels()/15 *j;
+   Serial.println(j);
+      //start = start-1;
+          for (uint16_t i = start; i > start - 35; i--){
+          strip.setPixelColor(i-1, c);
+         }
+          strip.show();
+  delay(wait);
+  }
+
+ }
+
+
+
+


Create photobooth.ino

Create photobooth.ino

Initial release.

error: pathspec 'arduino/photobooth.ino' did not match any file(s) known to git

--- arduino/photobooth.ino
+++ arduino/photobooth.ino
@@ -0,0 +1,476 @@
+/*
+  Arduino Photobooth
+
+  Harm Aldick - 2015
+  http://www.kitesurfer1404.de/tech/photobooth/en
+  https://github.com/kitesurfer1404/photobooth
+
+
+  FEATURES
+    * 7-segment-display for countdown
+    * LED-speedlights
+    * Pushbutton-support
+    * "breathing" pushbutton-LED
+    * Standalone or remote controlled operation (USB-serial)
+
+
+  NOTES
+    * Pushbutton-pins are configured to use internal pullup resistors
+      of the Arduino for less external parts. If you want to use external
+      pullup resistors change INPUT_PULLUP to INPUT in setup().
+    * Set your camera to continuous focus for best results.
+    * Use exposure compensation to compensate the dimmed focusing light.
+      Values arround -1 EV work best for me in low light situations.
+    * You might also need to adjust values in takePhoto() to your needs.
+      Brightness and delays might be different with different LED-bulbs.
+    * Serial speed is 9600 Baud. See processCommand() for a complete
+      list of supported commands.
+    * There is support for multiple pushbuttons - although only one is used
+      by now. When connecting to a Raspberry Pi a second pushbutton might be
+      used to shut the Pi down due to its lack of a power-down-button.
+    * analogWrite() works only on Pins 3, 5, 6, 9, 10, 11 - that's why the LED-spots
+      are connected to pins 10, 11, 5, 6 so we can get dimmed focusing light.
+    * Make sure to connect all pushbutton LEDs to PWM outputs so the breathing
+      will work.
+    * Read the datasheet of your 7-segment-display for pin-layout.
+      Connect this way:
+
+       Segment     Pin (Arduino)
+          A         2
+          B         3
+          C         4
+          D         7
+          E         8
+          F        12
+          G        13
+
+      Use darlington array and and current limiting resistors as appropriate.
+    * See repository for example circuit.
+
+    * This software is free and provided "as is" - but I appreciate a donation when
+      you make money off it (e.g. as a commercial photographer).
+
+
+  LICENSE
+
+  The MIT License (MIT)
+
+  Copyright (c) 2015  Harm Aldick
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+
+
+  CHANGELOG
+
+  2016-01-16   Initial beta release
+
+*/
+
+
+/* This is where you might define different IO-pins */
+
+int segment_pins[] = { 2, 3, 4, 7, 8, 12, 13 }; // pins segments A-G of the display are connected to
+int spot_pins[] = { 10, 11, 5, 6 };             // pins the spot-lights are connected to, use PWM-pins here
+
+int pin_focus = 15;   // camera: focus (using analog pin A1 as digital output)
+int pin_shutter = 16; // camera: shutter (using analog pin A2 as digital output)
+
+int pushbutton_leds[] = { 9 };  // pin(s) on which the LED(s) of the pushbutton-switch(es) is/are connected to. Use PWM-pins here.
+int pushbutton_pins[] = { 14 }; // pin(s) on which the pushbutton(s) is/are connected to. Using analog pin A0 as digital input
+int lastButtonState[] = { 1 };  // saving the last state(s) of the button(s)
+
+
+/* Some magic configuration happening below. */
+
+byte segment_digits[10][7] = { // segments to light up on the corresponding index
+  { 1,1,1,1,1,1,0 },    // 0
+  { 0,1,1,0,0,0,0 },    // 1
+  { 1,1,0,1,1,0,1 },    // 2
+  { 1,1,1,1,0,0,1 },    // 3
+  { 0,1,1,0,0,1,1 },    // 4
+  { 1,0,1,1,0,1,1 },    // 5
+  { 1,0,1,1,1,1,1 },    // 6
+  { 1,1,1,0,0,0,0 },    // 7
+  { 1,1,1,1,1,1,1 },    // 8
+  { 1,1,1,1,0,1,1 }     // 9
+};
+
+int breath_delay_steps[] =       {   7,   9,  13, 15, 16, 17, 18, 930, 19, 18, 15, 13,   9,   7,   4,   5 }; // magic numbers for breathing LED
+int breath_brightness_steps[] =  { 150, 125, 100, 75, 50, 25, 16,  15, 16, 25, 50, 75, 100, 125, 150, 220 }; // even more magic numbers!
+
+// initial/default values for breathing LED
+#define breath_initial_brightness 15
+#define breath_initial_direction 1
+#define breath_initial_index 8
+#define breath_initial_delay 1
+
+int breath_brightness; // initial brightness of breathing LED
+int breath_direction;  // increase brightness
+int breath_index;      // start at index 8 of our magic numbers
+int breath_delay;      // no delay at startup, load values imidiately
+boolean breathing_enabled = true;  // enables/disables breathing LED at all.
+
+String inputCommand = "";         // a string to hold incoming data from serial
+boolean commandComplete = false;  // whether the command string is complete
+
+boolean mode_auto = true; // default is running in standalone-mode
+
+
+
+// The setup function runs once when you press reset or power the board.
+void setup() {
+  // Set all 7-segment-pins as output and turn LEDs off
+  for(int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
+    pinMode(segment_pins[i], OUTPUT);
+    digitalWrite(segment_pins[i], LOW);
+  }
+
+  // Turn all spots off.
+  for(int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
+    digitalWrite(spot_pins[i], 0);
+  }
+
+  // Set all pushbutton-LED-pins as output and turn LEDs off
+  for(int i = 0; i < sizeof(pushbutton_leds)/sizeof(int); i++) {
+    pinMode(pushbutton_leds[i], OUTPUT);
+    digitalWrite(pushbutton_leds[i], LOW);
+  }
+
+  // Set all pushbutton-pins as input and enable pullup resistor
+  for(int i = 0; i < sizeof(pushbutton_pins)/sizeof(int); i++) {
+    pinMode(pushbutton_pins[i], INPUT_PULLUP); // change INPUT_PULLUP to INPUT when there is an external pullup-resistor attached
+  }
+
+  // setup focus and shutter pins
+  pinMode(pin_focus, OUTPUT);
+  digitalWrite(pin_focus, LOW);
+  pinMode(pin_shutter, OUTPUT);
+  digitalWrite(pin_shutter, LOW);
+
+
+  Serial.begin(9600); // initialize serial
+
+  inputCommand.reserve(100); // reserve 100 bytes for the inputCommand
+
+  breathing_reset(); // reset breathing LEDs
+
+  Serial.println("ready"); // we're ready to rock!
+}
+
+
+/* turns all breathing LEDs gently on and resets everything for restart breathing */
+void breathing_reset() {
+  for(int i = 0; i <= 15; i++) {
+    for(int p = 0; p < sizeof(pushbutton_leds)/sizeof(int); p++) {
+      analogWrite(pushbutton_leds[p], i);
+    }
+    delay(10);
+  }
+
+  breathing_enabled = true;
+  breath_brightness = breath_initial_brightness;
+  breath_direction = breath_initial_direction;
+  breath_index = breath_initial_index;
+  breath_delay = breath_initial_delay;
+}
+
+
+/* turns all breathing LEDs off and disables breathing at all */
+void breathing_stop() {
+  for(int i = 0; i < sizeof(pushbutton_leds)/sizeof(int); i++) {
+    analogWrite(pushbutton_leds[i], 0);
+  }
+  breathing_enabled = false;
+}
+
+
+/* does one step in "breathing", so we don't block anything else too long. */
+void breathing_do_step() {
+  if(!breathing_enabled) {
+    return;  // nothing to do if disabled
+  }
+
+  breath_delay--;
+
+  // update brightness and delays when waited long enough
+  if(breath_delay == 0) {
+    // increase or decrese brightness
+    breath_brightness = breath_brightness + breath_direction;
+
+    // change direction when LED is fully lit or very dimm
+    if(breath_brightness == 255 || breath_brightness == 15) {
+      breath_direction *= -1;
+    }
+
+    // update index of current delay when target brightness is reached
+    if(breath_brightness == breath_brightness_steps[breath_index]) {
+      breath_index++;
+
+      // start over when the end is reached
+      if(breath_index == sizeof(breath_brightness_steps)/sizeof(int)) {
+        breath_index = 0;
+      }
+    }
+
+    // get new delay
+    breath_delay = breath_delay_steps[breath_index];
+
+    // set new brightness to all pushbutton leds
+    for(int i = 0; i < sizeof(pushbutton_leds)/sizeof(int); i++) {
+      analogWrite(pushbutton_leds[i], breath_brightness);
+    }
+
+  } else {
+    delay(1); // if we have still some rounds to go, wait 1ms and return
+  }
+}
+
+
+/* flashes the 7-segment-display in a fancy way */
+void animation_one(int wait) {
+  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
+    digitalWrite(segment_pins[i], LOW);
+  }
+
+  for(int n = 0; n < 5; n++) {
+    for (int i = 0; i < 6; i++) {
+      digitalWrite(segment_pins[i], HIGH);
+      delay(wait);
+      digitalWrite(segment_pins[i], LOW);
+    }
+  }
+}
+
+
+/* flashes the 7-segment-display in another fancy way */
+void animation_two(int wait) {
+  int animation[] = { 1, 2, 7, 5, 4, 3, 7, 6 };
+
+  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
+    digitalWrite(segment_pins[i], LOW);
+  }
+
+  for(int n = 0; n < 5; n++) {
+    for(int i = 0; i < 8; i++) {
+      int segment = animation[i] - 1;
+      digitalWrite(segment_pins[segment], HIGH);
+      delay(wait);
+      digitalWrite(segment_pins[segment], LOW);
+    }
+  }
+}
+
+
+/* flashes the spots in a fancy way */
+void animation_spots(int wait) {
+  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
+    spot_off(i);
+  }
+
+  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
+    spot_on(i);
+    delay(wait);
+    spot_off(i);
+  }
+}
+
+
+/* turns a single spot on */
+void spot_on(int i) {
+  analogWrite(spot_pins[i], 255);
+}
+
+
+/* turns a single spot off */
+void spot_off(int i) {
+  analogWrite(spot_pins[i], 0);
+}
+
+
+/* turns all spots on ("speedlight") */
+void spots_on() {
+  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
+    spot_on(i);
+  }
+}
+
+
+/* turns all spots off */
+void spots_off() {
+  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
+    spot_off(i);
+  }
+}
+
+
+/* turns all spots on (dimmed) for fucusing the camera in low light */
+void spots_dimm(int value) {
+  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
+    analogWrite(spot_pins[i], value);
+  }
+}
+
+
+/* displays a number on the 7-segment-display */
+void displayNumber(int n) {
+  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
+    digitalWrite(segment_pins[i], segment_digits[n][i]);
+  }
+}
+
+
+/* turns the 7-segment-display off */
+void display_off() {
+  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
+    digitalWrite(segment_pins[i], LOW);
+  }
+}
+
+
+/* turns every light off */
+void clearAll() {
+  spots_off();
+  display_off();
+  breathing_stop();
+}
+
+
+/* starts countdown and focusing, than takes picture */
+void takePhoto() {
+  Serial.println("Taking photo.");
+
+  spots_dimm(5);
+  digitalWrite(pin_focus, HIGH);
+
+  animation_one(50);
+
+  displayNumber(3);
+  delay(1000);
+  displayNumber(2);
+  delay(1000);
+  displayNumber(1);
+  delay(1000);
+
+  display_off();
+
+  //spots_on();
+  spots_dimm(100);
+  delay(75);
+  digitalWrite(pin_shutter, HIGH);
+
+  delay(400);
+
+  clearAll();
+
+  digitalWrite(pin_focus, LOW);
+  digitalWrite(pin_shutter, LOW);
+
+  Serial.println("Photo taken.");
+}
+
+
+/* checks received command and calls corresponding function */
+void processCommand(String cmd) {
+  if(cmd == "1") displayNumber(1);
+  if(cmd == "2") displayNumber(2);
+  if(cmd == "3") displayNumber(3);
+  if(cmd == "4") displayNumber(4);
+  if(cmd == "5") displayNumber(5);
+  if(cmd == "6") displayNumber(6);
+  if(cmd == "7") displayNumber(7);
+  if(cmd == "8") displayNumber(8);
+  if(cmd == "9") displayNumber(9);
+  if(cmd == "0") displayNumber(0);
+
+  if(cmd == "display off") display_off();
+
+  if(cmd == "spots on") spots_on();
+  if(cmd == "spots off") spots_off();
+  if(cmd == "spots dimm") spots_dimm(1);
+
+  if(cmd == "S1 on") spot_on(0);
+  if(cmd == "S1 off") spot_off(0);
+  if(cmd == "S2 on") spot_on(1);
+  if(cmd == "S2 off") spot_off(1);
+  if(cmd == "S3 on") spot_on(2);
+  if(cmd == "S3 off") spot_off(2);
+  if(cmd == "S4 on") spot_on(3);
+  if(cmd == "S4 off") spot_off(3);
+
+  if(cmd == "animation 1") animation_one(50);
+  if(cmd == "animation 2") animation_two(50);
+  if(cmd == "animation spots") animation_spots(100);
+
+  if(cmd == "clear") clearAll();
+
+  if(cmd == "mode auto") mode_auto = true;
+  if(cmd == "mode manual") mode_auto = false;
+
+  if(cmd == "take photo") takePhoto();
+}
+
+
+/* reads new input from serial to commandstring. Command is complete on \n */
+void serialEvent() {
+  while(Serial.available()) {
+    char inChar = (char)Serial.read();
+    if(inChar == '\n') {
+      commandComplete = true;
+    } else {
+      inputCommand += inChar;
+    }
+  }
+}
+
+// This loop function runs over and over again. Forever. Poor little thing.
+void loop() {
+
+  breathing_do_step(); // do one step in "breathing"
+
+  // check all pushbuttons for changes
+  for(int i = 0; i < sizeof(pushbutton_pins)/sizeof(int); i++) {
+    if(digitalRead(pushbutton_pins[i]) == LOW) {  // if button is pressed
+      if (lastButtonState[i] == HIGH) {             // and was not pressed before
+        lastButtonState[i] = LOW;                     // save current state (pressed)
+        if(mode_auto) {                               // in standalone-mode...
+          inputCommand = "take photo";                  // set command
+          commandComplete = true;
+        } else {                                      // in remote-controlled mode...
+          Serial.print("P");                            // notify computer which button was pressed
+          Serial.println(i);
+        }
+      }
+      delay(250);                                  // poor mans debouncing
+    } else {                                     // if button is not pressed
+      lastButtonState[i] = HIGH;                   // save state (released)
+    }
+  }
+
+
+  if(commandComplete) {
+    breathing_stop();             // stop breathing (turn LED off)
+    processCommand(inputCommand); // process command
+    breathing_reset();            // enable breathing again
+
+    inputCommand = "";            // reset the commandstring
+    commandComplete = false;      // reset command complete
+
+    Serial.println("ready");      // notify computer
+  }
+}


Add files via upload

Add files via upload

Rewrite of the lights-only code.

error: pathspec 'proton_pack_buttons_1.0.ino' did not match any file(s) known to git

--- proton_pack_buttons_1.0.ino
+++ proton_pack_buttons_1.0.ino
@@ -0,0 +1,438 @@
+// Proton pack
+
+int current_state = 0;  // Tracks what the pack should be doing.
+int previous_state = 0;
+
+// ===============================================================================================
+// TIMEKEEPING
+// ===============================================================================================
+unsigned long currentMillis = 0;
+unsigned long previousMillis_off = 0;  // will store last updated time.
+unsigned long previousMillis_on = 0;
+unsigned long previousMillis_fire = 0;
+unsigned long off_interval = 30;
+unsigned long pwrcl_interval = 70;     // interval at which to cycle lights (milliseconds).
+unsigned long firing_interval = 60;    // interval at which to cycle firing lights (milliseconds).
+unsigned long max_firing_interval = 50;
+unsigned long min_firing_interval = 30;
+unsigned long overheat_interval = 200;
+int overheat_cycles = 7;
+int overheat_counter = overheat_cycles;
+
+// ===============================================================================================
+// BUTTONS
+// ===============================================================================================
+#define DEBOUNCE 5  // button debouncer.
+// Pins 14, 15 and 16 are Analog 0, 1 and 2 respectively.
+int power_button = 14;
+int firing_button = 15;
+int music_button = 16;
+int power_button_state;
+int firing_button_state;
+int music_button_state;
+
+// ===============================================================================================
+// SHIFT REGISTERS
+// ===============================================================================================
+int latchPin = 8;
+int clockPinPWR = 6;  // Power cell
+int clockPinGUN = 18;  // Gun  (18 is analog pin 4 on arduino)
+////Pin connected to DS of 74HC595 (pin 14)
+int dataPinPWR = 7;  // Power cell
+int dataPinGUN = 19; // Gun (19 is analog pin 5 on arduino)
+
+//holders for information we're going to pass to shifting function
+byte dataPWRCL1;
+byte dataPWRCL2;
+byte dataGUN1;
+byte dataGUN2;
+byte dataGUNON1;
+byte dataGUNON2;
+// data arrays
+byte PWRCL1[15];
+byte PWRCL2[15];
+byte GUN1[26];
+byte GUN2[26];
+byte GUNON1[15];
+byte GUNON2[15];
+byte OHPWRCL1[2];
+byte OHPWRCL2[2];
+byte OHGUN1[2];
+byte OHGUN2[2];
+// track array position
+int power_cell_array_pos = 0;
+int gun_array_pos = 0;
+int gunactive_array_pos = 0;
+int overheat_array_pos = 0;
+
+
+int freeRam(void) {
+    extern int  __bss_end;
+    extern int  *__brkval;
+    int free_memory;
+    if((int)__brkval == 0) {
+        free_memory = ((int)&free_memory) - ((int)&__bss_end);
+    }
+    else {
+        free_memory = ((int)&free_memory) - ((int)__brkval);
+    }
+    return free_memory;
+}
+
+
+void setup() {
+    // set up serial port
+    Serial.begin(9600);
+    Serial.print("Free RAM: ");
+    Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!
+
+    // Make input & enable pull-up resistors on switch pins
+    Serial.println("Pull ups on switches");
+    digitalWrite(power_button, HIGH);
+    digitalWrite(firing_button, HIGH);
+    digitalWrite(music_button, HIGH);
+
+    // Populate light pattern arrays
+    Serial.println("Populating light arrays");
+    // power cell LEDs 0 through 7 then LEDs 8 through 15 (two shift registers)
+    PWRCL1[0] = B10000000;  PWRCL2[0] = B00000000;  //10000000 00000000
+    PWRCL1[1] = B11000000;  PWRCL2[1] = B00000000;  //11000000 00000000
+    PWRCL1[2] = B11100000;  PWRCL2[2] = B00000000;  //11100000 00000000
+    PWRCL1[3] = B11110000;  PWRCL2[3] = B00000000;  //11110000 00000000
+    PWRCL1[4] = B11111000;  PWRCL2[4] = B00000000;  //11111000 00000000
+    PWRCL1[5] = B11111100;  PWRCL2[5] = B00000000;  //11111100 00000000
+    PWRCL1[6] = B11111110;  PWRCL2[6] = B00000000;  //11111110 00000000
+    PWRCL1[7] = B11111111;  PWRCL2[7] = B00000000;  //11111111 00000000
+    PWRCL1[8] = B11111111;  PWRCL2[8] = B10000000;  //11111111 10000000
+    PWRCL1[9] = B11111111;  PWRCL2[9] = B11000000;  //11111111 11000000
+    PWRCL1[10] = B11111111; PWRCL2[10] = B11100000; //11111111 11100000
+    PWRCL1[11] = B11111111; PWRCL2[11] = B11110000; //11111111 11110000
+    PWRCL1[12] = B11111111; PWRCL2[12] = B11111000; //11111111 11111000
+    PWRCL1[13] = B11111111; PWRCL2[13] = B11111100; //11111111 11111100
+    PWRCL1[14] = B11111111; PWRCL2[14] = B11111110; //11111111 11111110
+
+    //Proton wand idle pattern - two shift registers
+    GUN1[0] = B01000000;  GUN2[0] = B00000000;  //01000000 00000000
+    GUN1[1] = B01000000;  GUN2[1] = B00000000;  //01000000 00000000
+    GUN1[2] = B01100000;  GUN2[2] = B00000000;  //01100000 00000000
+    GUN1[3] = B01110000;  GUN2[3] = B00000000;  //01110000 00000000
+    GUN1[4] = B01111000;  GUN2[4] = B00000000;  //01111000 00000000
+    GUN1[5] = B01111100;  GUN2[5] = B00000000;  //01111100 00000000
+    GUN1[6] = B01111110;  GUN2[6] = B00000000;  //01111110 00000000
+    GUN1[7] = B01111111;  GUN2[7] = B10000000;  //01111111 10000000
+    GUN1[8] = B01111111;  GUN2[8] = B11000000;  //01111111 11000000
+    GUN1[9] = B01111111;  GUN2[9] = B11100000;  //01111111 11100000
+    GUN1[10] = B01111111; GUN2[10] = B11110000; //01111111 11110000
+    GUN1[11] = B01111111; GUN2[11] = B11111000; //01111111 11111000
+    GUN1[12] = B01111111; GUN2[12] = B11111100; //01111111 11111100
+    GUN1[13] = B01111111; GUN2[13] = B11111110; //01111111 11111110
+    GUN1[14] = B01111111; GUN2[14] = B11111100; //01111111 11111100
+    GUN1[15] = B01111111; GUN2[15] = B11111000; //01111111 11111000
+    GUN1[16] = B01111111; GUN2[16] = B11110000; //01111111 11110000
+    GUN1[17] = B01111111; GUN2[17] = B11100000; //01111111 11100000
+    GUN1[18] = B01111111; GUN2[18] = B11000000; //01111111 11000000
+    GUN1[19] = B01111111; GUN2[19] = B10000000; //01111111 10000000
+    GUN1[20] = B01111111; GUN2[20] = B00000000; //01111111 00000000
+    GUN1[21] = B01111110; GUN2[21] = B00000000; //01111110 00000000
+    GUN1[22] = B01111100; GUN2[22] = B00000000; //01111100 00000000
+    GUN1[23] = B01111000; GUN2[23] = B00000000; //01111000 00000000
+    GUN1[24] = B01110000; GUN2[24] = B00000000; //01110000 00000000
+    GUN1[25] = B01100000; GUN2[25] = B00000000; //01100000 00000000
+    GUN1[26] = B01000000; GUN2[26] = B00000000; //01000000 00000000
+
+    // Proton wand firing pattern - two shift registers
+    // 10000000 and 00000001 used for GUN strobe
+    GUNON1[0] = B11000000;  GUNON2[0] = B00000010;  //1|1000000  0000001|0
+    GUNON1[1] = B00100000;  GUNON2[1] = B00000101;  //0|0100000  0000010|1
+    GUNON1[2] = B00010000;  GUNON2[2] = B00001000;  //1|0010000  0000100|0
+    GUNON1[3] = B10001000;  GUNON2[3] = B00010001;  //0|0001000  0001000|1
+    GUNON1[4] = B00000100;  GUNON2[4] = B00100000;  //1|0000100  0010000|0
+    GUNON1[5] = B00000010;  GUNON2[5] = B01000001;  //0|0000010  0100000|1
+    GUNON1[6] = B10000001;  GUNON2[6] = B10000000;  //1|0000001  1000000|0
+    GUNON1[7] = B00000001;  GUNON2[7] = B10000001;  //0|0000001  1000000|1
+    GUNON1[8] = B00000001;  GUNON2[8] = B10000000;  //1|0000001  1000000|0
+    GUNON1[9] = B10000010;  GUNON2[9] = B01000001;  //0|0000010  0100000|1
+    GUNON1[10] = B00000100; GUNON2[10] = B00100000; //1|0000100  0010000|0
+    GUNON1[11] = B00001000; GUNON2[11] = B00010001; //0|0001000  0001000|1
+    GUNON1[12] = B10010000; GUNON2[12] = B00001000; //1|0010000  0000100|0
+    GUNON1[13] = B00100000; GUNON2[13] = B00000101; //0|0100000  0000010|1
+    GUNON1[14] = B01000000; GUNON2[14] = B00000010; //1|1000000  0000001|0
+
+    // Overheat patterns
+    OHPWRCL1[0] = B00000000;  OHPWRCL2[0] = B00000000;
+    OHPWRCL1[1] = B11111111;  OHPWRCL2[1] = B11111111;
+    OHGUN1[0] = B00000000;  OHGUN2[0] = B00000000;
+    OHGUN1[1] = B01111111;  OHGUN2[1] = B11111110;
+
+    // Set pins for shift registers:
+    pinMode(latchPin, OUTPUT);      // shared between power cell and thrower
+    pinMode(clockPinPWR, OUTPUT);
+    pinMode(clockPinGUN, OUTPUT);
+    pinMode(dataPinPWR, OUTPUT);
+    pinMode(dataPinGUN, OUTPUT);
+    // Initialise Power cell and gun lights
+    Serial.println("Initialising lights.");
+    digitalWrite(latchPin, 0);
+    shiftOut(dataPinPWR, clockPinPWR, 0x00);
+    shiftOut(dataPinPWR, clockPinPWR, 0x00);
+    shiftOut(dataPinGUN, clockPinGUN, 0x40);
+    shiftOut(dataPinGUN, clockPinGUN, 0x00);
+    digitalWrite(latchPin, 1);
+
+}
+
+
+void loop() {
+    pack_state();
+    if (previous_state != current_state) {
+        Serial.print("STATE: ");
+        Serial.println(current_state);
+    }
+}
+
+
+void pack_state() {
+    previous_state = current_state;
+    switch (current_state) {
+        case 0:  // reset
+            current_state = 1;
+            pwrcl_interval = 70;
+            firing_interval = max_firing_interval;
+            overheat_counter = overheat_cycles;
+            break;
+
+        case 1:  // Start
+            power_button_state = digitalRead(power_button);
+            if (power_button_state == LOW) {
+                current_state = 2;
+            }
+            else {
+                current_state = 0;
+            }
+            break;
+
+        case 2: // Powered on
+            power_button_state = digitalRead(power_button);
+            firing_button_state = digitalRead(firing_button);
+            if (power_button_state == HIGH) {
+                current_state = 3;
+            }
+            if (firing_button_state == LOW) {
+                current_state = 4;
+            }
+            powered_on();
+            break;
+
+        case 3: // Power down
+            Serial.print("array positions: ");
+            Serial.print(power_cell_array_pos);
+            Serial.print(" : ");
+            Serial.println(gun_array_pos);
+            powered_down();
+            break;
+
+        case 4: // Firing
+            power_button_state = digitalRead(power_button);
+            firing_button_state = digitalRead(firing_button);
+            //Serial.print("Button states [power|firing]: ");
+            //Serial.print(power_button_state); Serial.print("|"); Serial.println(firing_button_state);
+            if ((power_button_state == HIGH) && (firing_button_state == LOW)) {
+                current_state = 3;
+            }
+            if (firing_button_state == HIGH) {
+                current_state = 0;
+            }
+            firing();
+            break;
+
+        case 5: // Overheat
+            overheat();
+            break;
+
+        case 6: // Overheat lockout
+            firing_button_state = digitalRead(firing_button);
+            if (firing_button_state == HIGH) {
+                current_state = 0;
+            }
+            break;
+    }
+}
+
+
+void powered_on() {
+    currentMillis = millis();
+    if (currentMillis - previousMillis_on > pwrcl_interval) {
+        previousMillis_on = currentMillis;
+        // Load the light sequence from arrays
+        dataPWRCL1 = PWRCL1[power_cell_array_pos];
+        dataPWRCL2 = PWRCL2[power_cell_array_pos];
+        dataGUN1 = GUN1[gun_array_pos];
+        dataGUN2 = GUN2[gun_array_pos];
+
+        digitalWrite(latchPin, 0);  // Low to send data
+        // Send data to shift registers:
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL1);
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL2);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUN1);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUN2);
+        digitalWrite(latchPin, 1);  // high to make shift register output data.
+
+        power_cell_array_pos++;
+        if (power_cell_array_pos > 14) {
+             power_cell_array_pos = 0;
+        }
+        gun_array_pos++;
+        if (gun_array_pos > 25) {
+            gun_array_pos = 0;
+        }
+    }
+}
+
+
+void powered_down() {
+    currentMillis = millis();
+    if (currentMillis - previousMillis_on > off_interval) {
+        previousMillis_on = currentMillis;
+        if (gun_array_pos != power_cell_array_pos) {
+            gun_array_pos = power_cell_array_pos;
+        }
+        // Load the light sequence from arrays
+        Serial.print("PWR array: "); Serial.print(power_cell_array_pos);
+        Serial.print("  GUN array: "); Serial.println(gun_array_pos);
+
+        dataPWRCL1 = PWRCL1[power_cell_array_pos];
+        dataPWRCL2 = PWRCL2[power_cell_array_pos];
+        dataGUN1 = GUN1[gun_array_pos];
+        dataGUN2 = GUN2[gun_array_pos];
+
+        digitalWrite(latchPin, 0);  // Low to send data
+        // Send data to shift registers:
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL1);
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL2);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUN1);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUN2);
+        digitalWrite(latchPin, 1);  // high to make shift register show data.
+
+        power_cell_array_pos--;
+        if (power_cell_array_pos < 0) {
+            power_cell_array_pos = 0;
+            current_state = 0;
+        }
+        gun_array_pos--;
+        if (gun_array_pos < 0) {
+            gun_array_pos = 0;
+            current_state = 0;
+        }
+    }
+}
+
+
+void firing() {
+    currentMillis = millis();
+    if (currentMillis - previousMillis_on > firing_interval) {
+        previousMillis_on = currentMillis;
+        // Load the light sequence from arrays
+        dataPWRCL1 = PWRCL1[power_cell_array_pos];
+        dataPWRCL2 = PWRCL2[power_cell_array_pos];
+        dataGUNON1 = GUNON1[gunactive_array_pos];
+        dataGUNON2 = GUNON2[gunactive_array_pos];
+
+        digitalWrite(latchPin, 0);  // Low to send data
+        // Send data to shift registers:
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL1);
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL2);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUNON1);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUNON2);
+        digitalWrite(latchPin, 1);  // high to make shift register show data.
+
+        power_cell_array_pos++;
+        if (power_cell_array_pos > 14) {
+            firing_interval--;
+            power_cell_array_pos = 0;
+        }
+        gunactive_array_pos++;
+        if (gunactive_array_pos > 14) {
+            gunactive_array_pos = 0;
+        }
+        Serial.print("firing intervals: ");
+        Serial.print(firing_interval); Serial.print(" | "); Serial.println(min_firing_interval);
+        if (firing_interval < min_firing_interval) {
+            current_state = 5;
+        }
+    }
+}
+
+
+void overheat() {
+    currentMillis = millis();
+    if (currentMillis - previousMillis_on > overheat_interval) {
+        previousMillis_on = currentMillis;
+        overheat_array_pos = 1 - overheat_array_pos;
+        Serial.print("Overheat array pos: "); Serial.println(overheat_array_pos);
+        // Load the light sequence from arrays
+        dataPWRCL1 = OHPWRCL1[overheat_array_pos];
+        dataPWRCL2 = OHPWRCL2[overheat_array_pos];
+        dataGUN1 = OHGUN1[overheat_array_pos];
+        dataGUN2 = OHGUN2[overheat_array_pos];
+
+        digitalWrite(latchPin, 0);  // Low to send data
+        // Send data to shift registers:
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL1);
+        shiftOut(dataPinPWR, clockPinPWR, dataPWRCL2);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUN1);
+        shiftOut(dataPinGUN, clockPinGUN, dataGUN2);
+        digitalWrite(latchPin, 1);  // high to make shift register show data.
+
+        overheat_counter--;
+        if (overheat_counter < 0) {
+            current_state = 6;
+        }
+    }
+
+}
+
+
+void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
+    // This shifts 8 bits out MSB first,
+    // on the rising edge of the clock,
+    // clock idles low
+
+    // internal function setup
+    int i = 0;
+    int pinState;
+    pinMode(myClockPin, OUTPUT);
+    pinMode(myDataPin, OUTPUT);
+
+    //clear everything out just in case to
+    //prepare shift register for bit shifting
+    digitalWrite(myDataPin, 0);
+    digitalWrite(myClockPin, 0);
+
+    //for each bit in the byte myDataOut?
+    //NOTICE THAT WE ARE COUNTING DOWN in our for loop
+    //This means that %00000001 or "1" will go through such
+    //that it will be pin Q0 that lights.
+    for (i = 7; i >= 0; i--)  {
+        digitalWrite(myClockPin, 0);
+
+        //if the value passed to myDataOut and a bitmask result
+        // true then... so if we are at i=6 and our value is
+        // %11010100 it would the code compares it to %01000000
+        // and proceeds to set pinState to 1.
+        if ( myDataOut & (1 << i) ) {
+            pinState = 1;
+        }
+        else {
+            pinState = 0;
+        }
+
+        //Sets the pin to HIGH or LOW depending on pinState
+        digitalWrite(myDataPin, pinState);
+        //register shifts bits on upstroke of clock pin
+        digitalWrite(myClockPin, 1);
+        //zero the data pin after shift to prevent bleed through
+        digitalWrite(myDataPin, 0);
+    }
+    //stop shifting
+    digitalWrite(myClockPin, 0);
+}