Build your own ATtiny85 programmer using an UNO

attiny85programmerAs part of my ATTiny 85 learning adventure, I had to create some way to actually load code on to the 85 itself. My first go ’round was a breadboard monster. The thing I hate about bread boarding are the bloody wires.  What a mess. Once I got my game working, I set out for a better way to program the chip.  I could have bought one, but what’s the fun in that? As it turns out, it is simple to build, provided you have an Arduino UNO handy.

I decided to make a shield for the UNO. I wasn’t concerned with passing through all of the pins, so only the ones I needed are exposed.  This is something I won’t do often, so I made no attempt to pretty it up either.  The whole thing consists of an 8 pin socket, one six pin header and one ten pin header and a 10 uf capacitor. Oh, a small perf board to mount it all.

Wiring is tedious and made the same mistake as I did with the game (see my last post) as I got the four pins (5 to 8) reversed. I know, I know.

Mistake aside, it took about a half hour for me to wire it up.

One thing that was a bit problematic for me, as I have a vision impairment, was getting the pins lined up to the proper UNO pins for the headers.  That took a few tries, but I got it.

The connections are below for using an UNO:

UNO Pins

ATTiny 85 Pins (actual pin)

+5v Vcc (8)
Gnd Gnd (4)
Pin 13 pb2 (7)
Pin 12 pb1 (6)
Pin 11 pb0 (5)
Pin 10 reset pb5 (1)

In the table above, the left is the Uno, the right is the ATTiny 85 socket. You need a 10uf cap between the Uno gnd and reset.

Before you can do anything with the Arduino IDE and the 85, you must first install the support…

By default Arduino IDE doesn’t support ATtiny85 so we should add ATtiny boards to Arduino IDE. Open File -> Preferences and in the Additional Boards Manager URLs give this url Arduino IDE Attiny support. Then, open Tools -> Board -> Board Manager, scroll down the list where it says “attiny by Davis A. Mellis”. Click toinstall it. Once installed, you can select ATtiny as the board type. You will also have to select chip type (45,85,etc.) Along with the processor, you will also need to specify the speed.  1 Mhz is the default, I used 8 Mhz for the code I downloaded for the game. Adjust to suit your needs.

You also need to upload the ‘ArduinoISP’ sketch to the UNO before programming the ATTiny 85. Once you upload this sketch, the UNO will pass along to the 85 what ever you send.

For my little handheld, I had to burn the bootloader first, then upload the game sketch. Don’t forget to  set the Arduino IDE to ‘Programmer ‘Arduino as ISP’. Once the bootloader is burned to ATtiny, you are ready to upload your code.

You should be good to go.  Here is a site (from Arduino) that goes into far greater detail.

A Programming Language for a Portable Development System

Prototyping with Arduino and compatibles is fairly easy, especially when it comes to the hardware.  A breadboard simplifies things quite a bit.  A few months ago, I realized that I did not have any, so I purchased one, in a kit, on Amazon from a company called Elagoo. The kit, for about sixteen dollars (US) contained a lot of parts and the breadboard. Well, the board is fairly small, so I decided to create a portable workspace and mount the breadboard, an Arduino UNO R3 clone, a 2 x 16 LCD and some cord organizers.  It works great, and I can take my project around. Nice.  Problem, though, is that I still need to be tethered to the computer in order to write code.

WP_20161001_18_38_08_Pro_LI (2)This got me thinking…could I come up with a small but easy to use interface language that could be coded with nothing more than a 12 key keypad?

The answer is yes.  So, I have come up with an initial set of opcodes for programming with nothing more than what is on my workspace. 

This language would more resemble CHIP-8 than, say, the Arduino language.  Commands, statements and functions all use a single byte but can have one or more subsequent values for parameters.

The tables below outline the main features. The keypad I am using (because it was less than a buck) does not have enough keys for full hexadecimal, so I had to improvise. Still working on a scheme to allow alphanumeric entry without connecting a full ASCII keyboard.  For now, the language will be limited to reading sensors, accepting decimal (though integer only) numbers. No video, serial out to the 2×16 LCD or a Bluetooth module.

For the tables, the first column is the opcode, second is what the opcode does, third is any parameter( s ) necessary and the last is a description.

Assignment:

01

Let

Var (00-0F)

Value (00-FF)

Conditionals:

02

IF

Var (00-0F)

01 is equal, 02 is <, 03 is >, 04 is <>

03

Jump if true

Addr (00-FF)

 

Program Flow:

04

Goto

Addr (00-FF)

Transfer control to address

05

Call

Addr (00-FF)

Call a subroutine

06

Return

   

07

End

 

Ends program

Input/Output

10

Inkey

Var (00-0F)

Gets input from the keyboard

11

Out

Var (00-0F)

Outputs a value

12

Temp

Var (00-0F)

Gets a reading from the temperature sensor

13

Pinset

00-FF

Send a value to pin

14

Pinread

00-FF

Get a value from pin

15

Xfer Pin

Var (00-0F)

Transfers value from read pin to variable

I would envision the interpreter being fairly small, so it may be possible to integrate several libraries for the more popular sensors, like DHT-11 temp sensor and others.

So, what do you think?  Is this something of interest? Please post your thoughts in the comments below.

Apple, you are done…Microsoft, your dominance is near the end and Google, welcome aboard: how Android won the game, via Chrombooks

Change. It is a difficult thing to go through, but, it is inevitable. Nearly thirty years ago, CP/M was THE operating system and 8080/Z80 based computers were THE thing. I remember thinking they’d be around FOREVER. They didn’t make it past 1986, when IBM began to take over the personal computer industry. And, so, we are near that crossroad today.

Google has announced that Android apps will be available ‘soon’ for ChromeOS. That is, as they say, a game changer.

Why?

Well Chromebooks are inexpensive. Small computers using ChromeOS are inexpensive and do not need Wintel level power to do things.  Android apps, likewise, are mostly designed to run on cheap smartphones with power that comes close to that of a cheap desktop or laptop computer.  Combine the two and…WOW…that is a game changer, folks.

A friend of mine (one day, Sam, we will meet in person) has been touting these Chromebook things for a few years now.  I’ve always kind of poo-poo’ed them as being a browser on a minimalist Linux.  However, you put Android abilities in there and…BOOM!   A real challenge to Wintel.

Chromebooks already outsell the Macintosh. It will be a while before they supplant Windows, but, I think the writing is on the wall.  I am a die hard Windows fan. I’ve loved the environment and, later, the operating system since the 2.1 days. But, change is inevitable and Microsoft knows this. Pretty much the only product they still sell that is not completely available on other platforms is the Visual Studio development tool suite. And, I think, it won’t be long and you will be using that on Android. On a Chromebook. 

So, how is Google doing this? Merging the two operating systems?

No. No merging.  No AppV or Virtual machines either. NO, they are using containers that have the Android framework embedded in them.  This is a quite clever approach as it not only allows the app to ‘see’ the underlying filesystem and hardware it is running on, it also means apps can talk to each other and that is HUGE.  What good is a photo editor that cannot get to the photos?

It also means the applications run AT FULL SPEED.  Think about that.  Now the Android GAME world is open to ChromeOS.  In fact ALL Android apps will work this way, no developer changes required. Candy Crush Jelly Donuts and Coffee will run, full speed, full screen, on a cheap $120 (US) Chromebook just as well as it does on that Moto G.  This, my friends, is not only cool, but awesome.

I am no fan of Google, but this is a clever and very smart way to bring Android into the home in something other than a phone.

Now, I need to buy myself a Chromebook, get a good book on Java development and retool myself.  Apple, you need to get a clue. Your walled garden is about to be overtaken by weeds when your gardeners leave for greener pastures.  From Google.

You can read more about it here.

Third Party Boards Won’t Compile in Arduino IDE after an Upgrade? Read on to see how to fix it

So, I finally upgraded my Arduino IDE software to 1.6.7 and, as a result, none of the ATTINY boards would compile…Neither the digispark or Adafruit trinket. All I got was the error:
Board digispark-tiny (platform avr, package digistump) is unknown.
for the Digispark.

After some research, I found a solution for Windows:

  • You need to remove all of the board definitions from Arduino.
  • Open Board Manager and REMOVE all non-Arduino boards you have installed
  • Close board manager
  • Goto Preferences and remove the board url’s there
  • Next, open Explorer in Windows and navigate to: C:\Users\youruserdirectory\AppData\Local\Arduino15\packages and remove the directories under packages
  • Restart Arduino and then add the boards back

This should take care of the problem. You can fix it in Linux by following the same directions. The Linux equivalent of the Windows User directory would be your user directory\Arduino15…

Giving your Arduino projects ‘sight’ and ‘touch’: using IR, Photocells and Touch Sensors to your project

12419231_974683622601393_320731550894605287_oOK, so I am taking some liberty here with the terms sight and touch, but it got your attention, yes?

In this post, I am going to briefly share how to use three sensors: a ‘light detector’ or photocell, a touch sensitive ‘button’ and an IR receiver.

These three sensors all came from a company called ‘OSEPP’, but similar sensors can be had from other vendors as well.  I am going to write about these three specific sensors, but you should be able to adapt the information to what ever you have.  I will present code in both Tiny Basic and Arduino.

LIGHT SENSOR

• 3 pin outs: GRD (-) VCC (+) S ( Signal)

• Suitable supply voltage: +3 to 5Vdc
• Analog voltage output: 0 to 5 Vdc
• Detects ambient light density
• Works with CdsPhotoresistor
• Interface with microcontrollers and logic circuits • Analog sensors
• Uses PH 2.0 socket
• Special sensor with Arduino expansion boards

The light sensor is a cool photocell that is mounted on little breakout board, making it easier to use in a project. There are three pins: VCC, GND and Signal. Signal would connect to any of the Analog pins. When in use, it not only will let you know if it detects light, but also returns the intensity. The higher the value, the more light it detects. Reading it easy and you do not need any libraries. See the HalfByte Tiny Basic example below.

100 CLS
110 L=0: # PIN A0
120 P=13:# PIN 13 LED
130 A=AREAD(L)
140 IF A>299 DWRITE P, 0
150 IF A<300 DWRITE P, 1
160 CURSOR 0,0
170 ?”Intensity: “, A,” ”
180 DELAY 250
190 GOTO 130

What this little piece of code will do is turn on the LED if the light level drops below 300 and turns it off if it goes above 299. It also writes the level to the screen.

if you add a line, say 155, you can test for no light:
155 IF A=0 CLS: ?”NO LIGHT DETECTED”:DELAY 2000

Or, you can test for too much light:
155 IF A>=600 CLS:?”THE LIGHT IS TOO BRIGHT.”:DELAY 2000

There are many things you can do, for example, control a servo that turns an armature to open a food door to distribute dog food to a dish when the sun comes up.

You can use it to log when the sun comes, goes down. Use it control lighting, etc.

Here’s the Arduino sample:

/* OSEPP example of measured ambient light intensity from photocell .
depending on brightness, an LED brightness is changed.
more light = brighter LED. */

int photocellPin = A0;    // photocell sensor input
int ledPin = 11;      // select the pin for the LED
int photocellValue = 0;  // variable to store the value coming from the photocell val

void setup() {
Serial.begin(9600);

}

void loop() {
// read the value from the sensor:
photocellValue = analogRead(photocellPin); 
photocellValue = constrain(photocellValue, 200, 800); //adjust depending on environment.  
   
  // change brightness of LED depending on light intensity of photocell
  int ledbrightness = map(photocellValue, 200, 800, 0, 255);
 
  Serial.print(“incoming value from photocell sensor =”);
  Serial.println( photocellValue);
  analogWrite(ledPin, ledbrightness); 
  delay(100);       
}

TOUCH SENSOR

• 3 pin outs: G (GRD) V (VCC) S ( Signal)Basic wiring scheme for all three sensors.
• 3-5 V operating range
• 5 mA minimum current requirement.
• Capacitive touch detection

The touch sensor detects when you are touching the plate on the breakout board.  As long as you are touching the sensor, it returns a value.  You can test the value and determine if there is someone touching the sensor.

Arduino Code:

/*

OSEPP Touch Sensor Module Example

Serial monitor prints values output from touch sensor
when body conductivity applied.
*/

int sensorPin = A0;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() {
  Serial.begin(9600);
  // declare the ledPin as an OUTPUT:
}

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.println(“Touch Sensor Value = ” + sensorValue);

}

Tiny Basic Code:

100 CLS
110 L=0: # PIN A0
120 P=13:# PIN 13 LED
130 A=AREAD(L)
140 IF A>100 DWRITE P, 0
150 IF A<100 DWRITE P, 1
160 CURSOR 0,0
170 ?”Value: “, A,” ”
180 DELAY 250
190 GOTO 130

The Tiny Basic, very similar to the light sensor code, will turn the LED on and off each time you press the sensor.  On my setup, the values switch between 22 and 1023.  Your mileage may vary.

IR Sensor12792206_974716205931468_7006422127672690003_o

• 100% Arduino Compatible
• 3 pin outs: G –Ground V – 5V S – Signal
• Operates at a frequency of 38khz

The IR Sensor allows control of a circuit via an Infra Red remote or other IR source.  It works very much like the other two sensors here: has a ground, voltage and signal pins.  It returns values based on the IR signal received.  Admittedly, I have not yet done much with the sensor, so I have limited experience with it.  You can use the same Tiny Basic example from the Touch Sensor above.

Arduino Code:

/*
infrared sensor reciver. connect signal of infrared to analog pin 0. as the distance
from an object to sensor increases/decreases, you will increase/decrease
speed of led blinks from HIGH to LOW

*/

int IR_Pin = A0;    // select the input pin for the potentiometer
int IR_Value = 0;  // variable to store the value coming from the sensor

void setup() {
  // declare the ledPin as an OUTPUT:
  Serial.begin(9600);
}

void loop() {
  // read the value from the sensor:
  IR_Value = analogRead(IR_Pin);   
 
Serial.println(“delay value for LED = “+ IR_Value);  //what value are we reading once an IR led is detected?

// IR_VALUE  = constrain(IR_VALUE, 0, 100); // optional to add a strict range
}

In each of the examples above, the sensors are connected to the HalfByte Console (or your Arduino compatible) via pin A0.  You can use what ever analog pins you want, just change the reference in the code.  You can use them together as well.

Building a WiFi based Room Monitor using an ESP8266 and an Arduino compatible

BeautifulPhoto635888272313367045Having purchased a few of the ESP8266 WiFi modules, I decided to devote one of them to a room monitoring device.  I live i a fairly good sized home, with an oversized garage. The room over the garage is a bedroom.  Well, the room, while nicely insulated, is huge and is difficult to maintain the same temperature as the rest of the upstairs.  And, since it is a bedroom where a child who has a problem maintaining his body temperature sleeps and plays, we need to keep an eye on the temp in that room.

I did have an Arduino UNO with the ethernet shield and a DHT11 sensor in the room, but the ethernet sheild did not work well with the WiFi extender I have in the room.  And, wanting to actually build something specifically for the purpose at hand, I decided to design and build a solution around the wifi module.

It needed to be simple and, preferably, run off of a battery.  While I have not yet gotten to WP_20160106_15_27_46_Pro_LIthe battery solution yet, I do have the rest built and am working on the code.

The whole thing fits on a 2.5 by 2inch perf board. It features an Atmega 328 chip, a Nokia 5110 LCD, DHT11 temp/humidity module, the aforementioned ESP8266 module, LED’s, a few caps and resistors and a 16mhz crystal.

WP_20160112_22_25_33_Pro_LIAssembly was easy.  Remembering the cathode on an LED…that’s hard, for me.  I always hated those damn things.  I love blinky lights, but can’t stand to wire up the things.  UGH.  Anyway, I’m only using a few of the I/O pins on the 328: Serial in and out, D2, A4, A5 and, for the LCD, D3 through D7.  This leaves a few pins for you to use if you wish to expand the capabilities of the device.

I started out by soldering the socket for the chip.  Then, I wired up the reset, which is pin 1 to a WP_20160119_22_28_27_Pro_LImomentary push button connected to ground.  I then wired up pin 13 to an LED via a 150 ohm resistor, connected to ground. Power (pin 7) and  ground (pin 8) were next.  You can test, at this point, by inserting a 328 that has the standard Arduino bootloader and nothing else burned into the chip. Insert the chip, apply five volts and the LED should blink.  If so, congrats!

You can install a power on LED as well.  Solder an LED and 150 ohm resistor to ground and Pin 7. When power is applied, the LED should light up.

The crystal was next.  Solder the crystal to pins 9 and 10.  Solder a 22pF capacitor to each each pin of the crystal and tie them to ground.

If you are at this point, congratulations, you have built a very basic Arduino compatible microcontroller. 

WP_20160115_18_50_02_Pro_LIFrom this point, I soldered some headers so I could connect serial I/O, power and the connections for the DHT11 and RTC (1307).   I then soldered the Nokia 5110 to the board and connected it as follows:

pin 7 – Serial clock out (SCLK)
pin 6 – Serial data out (DIN)
pin 5 – Data/Command select (D/C)
pin 4 – LCD chip select (CS)
pin 3 – LCD reset (RST)

Connect pin 6 on the LCD to +5, pin 8 to Ground and pin 7 to +5 if you want the back light. I connected a switch to my display so I could turn the light on or off.  Add the swtich between the +5 and pin 7 if you wish.

I uploaded a demo 5110 sketch to make sure the screen worked. It did.

The DHT only has one data pin, the middle pin, and it goes to D2 on the chip.  Connect the others to +5 and ground.

WP_20160118_00_04_44_Pro_LI (2)As the ESP8266 is intolerant of higher voltages, I installed a 3.3v regulator to power the module.  I grab a five volt line, solder it to the right pin of the to220 regulator, the left most pin to ground and the middle pin to the VCC pin on the 8266.  The TX line from the 8266 goes to D0 on the 328, the RX line to D1 and, ground to ground. You also, if you have the v1 of the module, connect power to the chip select pin (4) of the 8266 as well as connect its RST pin to the reset pin of the 328. 

The RTC (real time clock) is connected:
SCL to A5 on 328
SDA to A4 on 328
VCC to +5
GND to ground

Connect it all up and you have a complete wifi based room monitor. For now, it returns the temperature and humidity.  At somepoint, I am going to return a timestamp so I graph the data and figure out when the temperature spikes or cools. 

Software

WP_20160122_13_12_55_Pro_LIGetting the LCD to display the date, time, temperature and humidity was simple.  The issue I have is with the wifi module. And it is also keeping me from posting a complete solution. So, I am going to post what I have. If one of you can figure out the webserver piece, please share it with us. I am sure it is something I am doing wrong. 

The code is at the end of this post.

Building things from ‘scratch’ is far more rewarding than just connecting a few sensors to an UNO or some other board.  But, you can do that if you wish.  At any rate, no matter what you do, YOU are still doing it and that is what matters. 

Code:

/*********************************************************************
* This sketch uses the Adafruit libraries for Monochrome Nokia 5110 LCD Displays
*
* Pick one up today in the adafruit shop!
* ——> http://www.adafruit.com/products/338
*
* These displays use SPI to communicate, 4 or 5 pins are required to
* interface
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Limor Fried/Ladyada  for Adafruit Industries.
* BSD license, check license.txt for more information
* All text above, and the splash screen must be included in any redistribution
*********************************************************************/

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include “DHT.h”
#include <Wire.h>
#include “RTClib.h”

#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];

DHT dht;
RTC_DS1307 rtc;

// pin 7 – Serial clock out (SCLK)
// pin 6 – Serial data out (DIN)
// pin 5 – Data/Command select (D/C)
// pin 4 – LCD chip select (CS)
// pin 3 – LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);

// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM __attribute__((section(“.progmem.vars”)))
#endif
const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000001, B10000000,
  B00000011, B11000000,
  B00000111, B11100000,
  B00001111, B11110000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000,
  B00000000, B00000000
};
#define SCREENWIDTH 84
#define SCREENHEIGHT 48

#define DEBUG true
const int ESP8266_CHPD = 4;
int isConnected = false;

void setup() {

  display.begin();
  Wire.begin();
  rtc.begin();
  //rtc.adjust(DateTime(__DATE__, __TIME__));
  if (! rtc.isrunning()) {
    display.println(“RTC is NOT running!”);
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }
  Serial.begin(115200); // your esp’s baud rate might be different
  Serial.setTimeout(5000);
  Serial.println(“AT+RST”);

  if (Serial.find(“ready”))
  {
    display.println(“Module is ready”);
    isConnected = true;
    display.drawBitmap(0, 0, logo16_glcd_bmp, 16, 16, BLACK);
    display.display();
  }
  else
  {
    display.println(“Module have no response.”);
    display.display();
    setup();
  }
  Serial.print(“AT+CWMODE=1\r\n”);
  Serial.print(“AT+CWJAP=\”xxx\”,\”xxx\”\r\n”);  //replace xxx with your ssid and password
  Serial.print(“AT+CIFSR\r\n”);
  Serial.print(“AT+CIPMUX=1\r\n”);
  Serial.print(“AT+CIPSERVER=1,80\r\n”);
  display.println(Serial.read());
  display.setContrast(50);
  dht.setup(2); // data pin 2
  display.display(); // show splashscreen
  delay(2000);
  display.clearDisplay();   // clears the screen and buffer
  display.display();
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.println(“HalfByte Room    Monitor”);

  display.display();
  delay(3000);
  display.clearDisplay();
  display.setTextSize(1);
}

void loop() {
  int ch_id, packet_len;
  char *pb;
  Serial.readBytesUntil(‘\n’, buffer, BUFFER_SIZE);

  delay(dht.getMinimumSamplingPeriod());

  float humidity = dht.getHumidity();
  float temperature = dht.getTemperature();

  display.clearDisplay();
  display.display();
  if (isConnected == true) {
    display.drawBitmap(70, 0, logo16_glcd_bmp, 16, 16, BLACK);
    display.display();
  }
  display.setCursor(3, 29);
  display.print(“Humidity: “);
  display.setCursor(display.width() / 2, 38);
  display.print(humidity, 1);
  display.print(“%”);
  display.setCursor(3, 20);
  display.print(“Temp: “);
  display.setCursor(40, 20);
  display.print(dht.toFahrenheit(temperature), 1);
  display.print(“F”);
  display.drawRect(0, 28, display.width(), 19, BLACK);
  display.display();

  DateTime now = rtc.now();
  display.setCursor((display.width() / 2) – 35, 1);
  if (now.month() < 10) display.print(0);
  display.print(now.month(), DEC);
  display.print(‘/’);
  if (now.day() < 10) display.print(0);
  display.print(now.day(), DEC);
  display.print(‘/’);
  display.print(now.year(), DEC);
  display.setCursor((display.width() / 2) – 30, 12);
  if (now.hour() < 10) display.print(0);
  display.print(now.hour(), DEC);
  display.print(‘:’);
  if (now.minute() < 10) display.print(0);
  display.print(now.minute(), DEC);
  display.print(‘:’);
  if (now.second() < 10) display.print(0);
  display.print(now.second(), DEC);
  display.display();

  if (strncmp(buffer, “+IPD,”, 5) == 0) {
    // request: +IPD,ch,len:data
    sscanf(buffer + 5, “%d,%d”, &ch_id, &packet_len);
    if (packet_len > 0) {
      // read serial until packet_len character received
      // start from :
      pb = buffer + 5;
      while (*pb != ‘:’) pb++;
      pb++;
      if (strncmp(pb, “GET / “, 6) == 0)
        //if (Serial.available()) // check if the esp is sending a message
        //{
        if (Serial.find(“+IPD,”))
        {
          //delay(1000);
          delay(100);
          clearSerialBuffer();
          int connectionId = Serial.read() – 48; // subtract 48 because the read() function returns
          display.print(connectionId);
          display.display();
          // the ASCII decimal value and 0 (the first decimal number) starts at 48
          homepage(connectionId);
        }
    }
  }
}

void homepage(int ch_id) {
  String Header;
  float temperature = dht.getTemperature();
  Header =  “HTTP/1.1 200 OK\r\n”;
  Header += “Content-Type: text/html\r\n”;
  Header += “Connection: close\r\n”;
  Header += “Refresh: 5\r\n”;

  String Content;
  Content = “Environmental Status:<br/>”;
  Content += String(“<B>Temperature:</b>”);
  Content += String(dht.toFahrenheit(temperature));
  Content += String(“<br><b>Humidity: </b>”);
  Content += String(dht.getHumidity());
  Header += “Content-Length: “;
  Header += (int)(Content.length());
  Header += “\r\n\r\n”;

  Serial.print(“AT+CIPSEND=”);
  Serial.print(ch_id);
  Serial.print(“,”);
  Serial.println(Header.length() + Content.length());
  delay(10);

  //if (Serial.find(“>”))
  {
    Serial.print(Header);
    Serial.print(Content);
    Serial.println(“AT+CIPCLOSE=0”);

    delay(10);
  }
}

// Get the data from the WiFi module and send it to the debug serial port
String GetResponse(String AT_Command, int wait) {
  String tmpData;

  Serial.println(AT_Command);
  delay(10);
  while (Serial.available() > 0 )  {
    char c = Serial.read();
    tmpData += c;

    if ( tmpData.indexOf(AT_Command) > -1 )
      tmpData = “”;
    else
      tmpData.trim();

  }
  return tmpData;
}

void clearSerialBuffer(void) {
  while ( Serial.available() > 0 ) {
    Serial.read();
  }
}

void clearBuffer(void) {
  for (int i = 0; i < BUFFER_SIZE; i++ ) {
    buffer[i] = 0;
  }
}

boolean connectWiFi(String NetworkSSID, String NetworkPASS) {
  String cmd = “AT+CWJAP=\””;
  cmd += NetworkSSID;
  cmd += “\”,\””;
  cmd += NetworkPASS;
  cmd += “\””;

  GetResponse(cmd, 10);
}

A Spark of Life: More DigiSpark fun

WP_20151019_22_42_59_Pro__highresI recently wrote about the cool little DigiSpark ATTiny 85 controller board. This little USB wonder, like the AdaFruit Trinket, is based on the ATTiny85 Microcontroller and has limited I/O, memory and is cheap, very cheap.

One thing it is not short on, however, is uses. This little thing can be used for a variety of things, including games and control applications.  For any use, though, you will need some kind of input and some kind of output.  In a previous post, I postulated about porting my ‘Battlestar Galactica’ game to the DigiSpark from the Trinket.  So, here are the results of that endeavor and some other things as well.

For the backstory of the game and why I wrote it, check out this post. I’ll wait.

Read it?  Cool.WP_20151019_22_44_34_Pro__highres

Ok, so there are few differences between the Trinket and the DigiSpark, other than size.  The way you program it is very similar and the pins are nearly identical.  The way you talk to things, is, however, a little different.

The Trinket needed SoftwareSerial. We don’t here, we just use DigitalRead and DigitalWrite and Serial.write to read the button and write to the screen.

The display is a 16×2 Serial LCD from Parallax.  The button is actually a ‘controller’ I built a couple of years ago for my game console. I did not use it for that, opting for the Wii Nunchuck instead.  So, the controller has three buttons that would be used for left, right and ‘fire’ or action.  Here, they just return a 0 if pressed and a 1 when ‘open’.  The code periodically polls the controller for a press and then acts on the press to evaluate a hit or miss.

WP_20151019_22_44_06_Pro__highres

Now, one of the problems I had was the lack of GROUND pins. So, I made a ground bus, a four pin strip with a wire connecting all four pins. I then connected this to ground on the DS and the button and the LCD as well are connected to this bus. I have one free ground pin.  Well, what I did not realize was that you can use any pin for ground.  While I did not change my connections, I find this pretty cool.

TIP! To use a free pin as ground:

(From the wiki)

You can use an I/O pin as a ground/+5V if you have some left and the current that flow in it is low (a few milliamps if you want the pin to stay around 0V/+5V. If you don’t care about the exact voltage you can go up to 40mA per pin according to the datasheet but it’s good to keep a safety margin).

Configure the pin as an output and set its value to either LOW or HIGH (for ground or +5V

#define button 0
#define gnd 2
 
void setup() {                
  pinMode (button, INPUT);
  digitalWrite (button, HIGH); // enable pullup
  pinMode(gnd, OUTPUT);
  digitalWrite (gnd, LOW); // use this pin as a ground
}

For much more information and tips, go to the wiki, located here.

The game code is below.

Come back for more on this cool little device.  Since it is capable of serial i/o, I’m thinking of using the Bluetooth Serial module and connecting the DS to one of my HalfByte Consoles running the graphical serial software for video display from the DS.

WP_20151019_22_45_35_Pro__highresWP_20151019_22_43_27_Pro__highres

Game Code:

#include <TinyPinChange.h>

 // globals
 int  cylonpos;
 int  oldcylonpos;
 int  cyDirection;
 int  button;
 int  posStart;
 int  lin2Start;
 int  bsgpos;
 
 // special characters
 int  bsg;
 int  cylon;
 
 // total number of torpedos the ship has left
 int  tShots=10;
 
 // the setup routine runs once when you press reset:
 void waitforbutton();
 void moveCylon();
 
 void setup() {  // initialize the digital pin as an output.  
   Serial.begin(9600); 
   Serial.write(12);
   Serial.write(17);
   
   //define the ship character
   Serial.write(249);
   Serial.write(0x4);
   Serial.write(0xE);
   Serial.write(0xE);
   Serial.write(0x15);
   Serial.write(0x1F);
   Serial.write(0x15);
   Serial.write(0xE);
   Serial.write(0xE);
   
   // baddies
   Serial.write(251);

   Serial.write(uint8_t(0x0));//to handle a goofy issue with '0'
   Serial.write(uint8_t(0x0));
   Serial.write(0xE);
   Serial.write(0x15);
   Serial.write(0x1F);
   Serial.write(uint8_t(0x0));
   Serial.write(uint8_t(0x0));
   Serial.write(uint8_t(0x0));
 
 // the button is on pin 0  
   pinMode(0,INPUT);
   
 // the initial direction is right
   cyDirection=1;
   
 } // the loop routine runs over and over again forever:
 void loop() {
  int score;
  score=0;
  
  Serial.write(12); // clear the screen and show the instructions
  Serial.println("Shoot the Cylon\n");
  Serial.println("press btn strt");
  
  // wait for the button
  waitforbutton();
  
  // define somethings before we start the game loop
  tShots=10;
  cylon=3;
  bsg=1;
  lin2Start=148; // the baddies appear on line 1
  posStart=128;  // the good guys on line 2
  randomSeed(analogRead(0)); // gen a random seed
  
  bsgpos = 8;  // our ship starts in the middle of the sector
  cylonpos=random(0,15); // baddies warp in at a random spot
  oldcylonpos=cylonpos;
  
  Serial.write(12);  // clear screen
  Serial.write(17);  // turn on backlight so we can see
  Serial.write(posStart + cylonpos);  // uh oh...the Cylon appeared!
 
  Serial.write(cylon);
  Serial.write(lin2Start+bsgpos);
  Serial.write(bsg); // and here we are
  
  // begin the game 
  while(1){
    /* Game loop */
    int button;
    Serial.write(22); // kill the cursor
    moveCylon();
    delay(200);
    button=digitalRead(0);  // check the button
    
    if(button==0){ // torpedo fired?
      if(cylonpos==bsgpos){ // Hit?
        Serial.write(132); // center 'Hit' on screen
        Serial.print("** HIT **");
        score ++;  // update score
        Serial.write(213); // noise (C at half note, 3rd scale)
        Serial.write(215); // play the note
        Serial.write(224);
        Serial.write(225);
        if(score==10){  // did we win?
           Serial.write(12); // clear screen
           Serial.write(128);// start at beginning
           Serial.print("You have saved\nthe Galactica.");
           delay(2000);
           loop();  // start game again
        }
        delay(3000); // did not win yet
        Serial.write(12); // clear screen
        Serial.write(lin2Start); // move cursor to beginning of line
        Serial.write("Score:");  // put up score
        Serial.print(score);
        Serial.write(lin2Start+bsgpos); // Since we shot the Cylon, we have to leave the sector, so...
        Serial.write(0x20); // go into hyperdrive and erase the BSG
        bsgpos=random(9,15);  // calculate new position
        Serial.write(lin2Start+bsgpos); //...and, we are here
        Serial.write(bsg);
        Serial.write(posStart+cylonpos);
        Serial.write(0x20);
        cylonpos=random(0,15); // Damn, they found us!
        oldcylonpos=cylonpos;
        moveCylon();
      } 
      
      tShots --; // decrement our torpedo inventory
      if(tShots<1){ // out of ammo?
        Serial.write(12);  // clear screen
        Serial.write(posStart); // start at beginning of line
        Serial.print("The Cylons win.\n");
        int count=1;
        // show animation of our ship exploding
        while (count<10){
          Serial.write(lin2Start+bsgpos);
          Serial.write(bsg);
          delay(500);
          Serial.write(lin2Start+bsgpos);
          Serial.write('*');
          delay(500);
          count++;
        }        
        loop(); // Play again
      }
    }  
  }
}
void moveCylon(){
  // sneaky Cylons...they show up anywhere!
  Serial.write(posStart+oldcylonpos);
  Serial.write(0x20);
  if (random(0,6)>3){
      //Cylon warped
      cylonpos=random(0,15);
      oldcylonpos=cylonpos;
  }
  
  cylonpos += cyDirection; // figure out which way to move
  if (cylonpos>15){
   cylonpos=15;
   cyDirection=-1;
  }
  
  if (cylonpos<0){
    cylonpos=0;
    cyDirection=1;
  }
  // erase from old spot
  Serial.write(posStart+oldcylonpos);
  Serial.write(0x20);
  Serial.write(posStart+cylonpos);
  Serial.write(cylon);
  oldcylonpos=cylonpos;
} 

void waitforbutton(){
   
  int button;
  button=digitalRead(0);
  while(button==1){     //wait for button press
    button=digitalRead(0);
    delay(1000);
  }  
  Serial.write(1);  
  delay(1000);
  Serial.write(12); 
}