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);
}

The ESP8266 WiFi Module–how to get it to work with an Arduino

WP_20160106_15_27_46_Pro_LIFinally got around to playing with the ESP8266 WiFi Module with an Arduino UNO.  I am using the UNO simply because it has a steady, 3.3v output while the HalfByte Console isn’t as steady and the module is, from everything I have read, is not tolerant of much more than the 3.3 volts.  Until I fix the console’s 3.3volt output, I will use the UNO.

Before I go on, I have to say, this little board isn’t very reliable. It is only connecting about a third of the time.

The documentation is spotty, even though it has been out for quite sometime now.  So, I hope to help anyone who just wants to use it as a WiFi module and not reprogram it to play Tic Tac Toe.

First, it is important to know which module you have as there are quite a few variations.  You go here to figure that out. The board I have is an ESP-01 Rev 2.  The Rev is important as you have a couple of extra steps from the rev 1 board.

From the wiki, here’s the pin out for the rev 2 board:

image

In order for this thing to work, you MUST jumper the CHIP_EN (or CHIP_PD) pin to the VCC pin, pulling the pin high.  This enables the whole thing to, you know, work. 

One other important detail…the baud rate is 115,200.  Most documentation I read said it was 9600, but, at least on mine, it is 115,200 baud.

Those two things were the key for me to get my module to connect and work.

Wiring it up is easy:image

ESP8266 ARDUINO
UTX RX (pin 0)
URX TX (pin 1)
GND GND
VCC 3.3V
CHIP_EN 3.3V
RST Reset

The code is straightforward enough. I copied an example from the wiki and modified it to work with my module and took out some extraneous junk.WP_20160106_15_59_14_Pro_LI (2)

Code:

#include <SoftwareSerial.h>
#define SSID        “xxx”
#define PASS        “xxx”
#define DST_IP      “173.194.116.116”    //google.com
SoftwareSerial dbgSerial(10, 11); // RX, TX
void setup() 
{
    // Open serial communications and wait for port to open:
    Serial.begin(115200);
    Serial.setTimeout(5000);
    dbgSerial.begin(9600);  //can’t be faster than 19200 for softserial
    dbgSerial.println(“ESP8266 Demo”);
    //test if the module is ready
    Serial.println(“AT+RST”);
    delay(1000);
    if(Serial.find(“ready”))
    {
        dbgSerial.println(“Module is ready”);
     }
    else
    {
        dbgSerial.println(“Module have no response.”);
        while(1);
     }
    delay(1000);
    //connect to the wifi
    boolean connected=false;
    for(int i=0;i<5;i++)
    {
    if(connectWiFi())
      {
      connected = true;
      break;
      }
    }
    if (!connected){while(1);}
      delay(5000);
      //set the single connection mode
      Serial.println(“AT+CIPMUX=0”);
}
void loop()
{
  String cmd = “AT+CIPSTART=\”TCP\”,\””;
  cmd += DST_IP;
  cmd += “\”,80″;
  Serial.println(cmd);
  dbgSerial.println(cmd);
  if(Serial.find(“Error”)) return;
  cmd = “GET / HTTP/1.0\r\n\r\n”;
  Serial.print(“AT+CIPSEND=”);
  Serial.println(cmd.length());
  if(Serial.find(“>”))
  {
    dbgSerial.print(“>”);
  }else
  {
    Serial.println(“AT+CIPCLOSE”);
    dbgSerial.println(“connect timeout”);
    delay(1000);
    return;
  }
  Serial.print(cmd);
  delay(2000);
  //Serial.find(“+IPD”);
  while (Serial.available())
  {
  char c = Serial.read();
  dbgSerial.write(c);
  if(c==’\r’) dbgSerial.print(‘\n’);
  }
  dbgSerial.println(“====”);
  delay(1000);
}
boolean connectWiFi()
{
  Serial.println(“AT+CWMODE=1”);
  String cmd=”AT+CWJAP=\””;
  cmd+=SSID;
  cmd+=”\”,\””;
  cmd+=PASS;
  cmd+=”\””;
  dbgSerial.println(cmd);
  Serial.println(cmd);
  delay(2000);
  if(Serial.find(“OK”))
  {
    dbgSerial.println(“OK, Connected to WiFi.”);
    return true;
  }else
  {
    dbgSerial.println(“Can not connect to the WiFi.”);
    return false;
  }
}

Because I am using the serial I/O on the UNO for the module, I used softwareserial to talk to a HalfByte Console running the HalfByte graphical terminal sketch so I could see the output of the module.  Normally, you would, likely, not have any kind of output on the Arduino as you’d be using the WiFi module for your I/O. I’m guessing.

I may order a few more of these things to play with reprogramming them and running code directly on them.  There is a Basic Language interpreter, LUA and Javascript for them, so I may play with that.  For now, IF I can get it working reliably, I may pair one with an ATTINY85, like a Trinket or DigiSpark, and a DHT11 temp sensor and set up a network of wireless thermometers in the house. 

I can see the potential, but the reliability is an issue.

Building your own hand held gaming console Part 1

WP_20151111_23_02_12_RichSince getting involved with Arduino and other Microcontrollers, I have designed and built several ‘consoles’ with the most involved one, the HalfByte Console Computer having its own PC Board designed and fabricated.  That was a fun project, well, they all have been, but this one was special: it was my first PC board design that was ‘produced’.   I also managed to design another console, but this was a game rig that went in an old Gameboy case.  This was only partially my design, as the 328 was actually an Arduino Mini Pro.  I added a sound amp, the screen and controller circuitry. So, it wasn’t entirely my design and it was a bit less satisfying. So…

I designed my own hand held from the ground up. This one, currently, lacks sound, and has a simpler controller: three buttons which translate into an action button, a left/up and right/down set of buttons. There is also a reset switch.

This design is very simple: it is a minimalist Arduino 328 compatible with four switches and a Nokia 5110 LCD screen.

WP_20151103_22_17_58_Rich_LIThe whole thing is on a perf board (in this case, it was a freebie board from Bay Area Circuits, go to their website and request the free boards, there Is a link for the request. These are very nice boards and a cool blue color.)

I started out by placing the parts on the board to see if I had room.  I did.

Be sure to photograph the board with the parts located where you wish to place them, this way you have a record of where you put them.

WP_20151103_23_11_54_Rich (2)

My initial design had only left and right buttons, no third button. I added that and the reset button to give me a bit more flexibility.

And, one lesson learned: socket the screen.  On the 5110, the thicker part of the bezel is the TOP, not the bottom.

For this project, you will need:

Quantity

Part Name

Value

2

Ceramic Capacitor

22pF

1

16MHZ Crystal

16MHZ

3

Resistor

220 ohm

1

AtMega 328P

328

1

28 DIP Socket

28 pin

4

Momentary Push Buttons

 

1

Red, LED

 

1

Resistor

150 ohm

1

Four pin header

 

1

5110 LCD

 

Parts placement is up to you, but I put the crystal and two caps under the screen, but you can put them where ever you want.

HalfByteHandheld2_schemI would start by placing the 28 pin socket and header on the board first. Solder them in place, use ample solder because you will have to solder wire to the socket and header. Use tape to hold them on the board while you solder them in place.

The LED is the only part that could be soldered in wrong because the key is hard to see. It is the flat side of the LED that is soldered to the resistor.

WP_20151109_22_44_49_Rich_LIOnce everything is soldered in place, insert your 328 controller chip and apply power.  If the 328 contains the standard Arduino boot loader, the pin 13 LED should blink.  If it does, congratulations! You now have a fully functional computer in your hand.

Some things I plan to add are sound and, perhaps, two more buttons.  I may add a video out option, but this is meant to be a handheld, so the video may not happen.

Stay tuned for part two, the software.

WP_20151111_23_04_16_Rich_LI

 

Short Video

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); 
}

The Mighty ATTiny85 and DigiSpark

Microcontrollers are lots of fun to play with as well as to build useful things.  They come in all sizes, shapes and varieties.  I am always, however, intrigued with the tiny controllers, like AdaFruit’s Trinket.  Well, the latest one I’ve started to tackle is the DigiSpark.  The DigiSpark is small and comes in several types. I am using the USB flavor. This little guy is on a very small board, about the size of a nickel, and is, itself, a USB dongle.

WP_20150928_23_59_09_Pro (2)

It features six I/O lines, plus power and ground pins.  This thing is a little bit more versatile than the original Trinket, but not much more. The USB version has the added advantage of being a USB dongle itself, meaning you can build a project that plugs into a USB port and act as an external controller. You don’t need USB, once you have programmed it, the power and ground pins can be used to power the device.

The nice thing about the DigiSpark is that you can use the Arduino IDE and SOME of the libraries to program the device.  There is a nice tutorial on setting up a newer release of the IDE and add DigiSpark support.

In a nutshell:

  1. Start the IDE (Install 1.6.x if you don’t already have it installed)
  2. Click FILE, then PREFERENCES
  3. in the Additional Boards Manager URL’s box, enter: http://digistump.com/package_digistump_index.json
  4. Click OK
  5. Click Tools, then BOARDS
  6. Select Board Manager and then Contributed
  7. In the dialog box that pops up, select DIGISTUMP AVR BOARDS
  8. Click Install
  9. Close the Board Manager
  10. You should now see the DigiSpark boards in the IDE

The thing that tripped me up was uploading a sketch.  I didn’t realize that you don’t need to have the device plugged in prior to uploading (you are told this, but it didn’t sink in.)  Once I unplugged the device, clicked upload and THEN plugged it in, it worked like a charm.

So, now I have to figure out what I want to do with this cool little device. 

But, wait…I still have not really said anything about the device, what it has on it, etc.

It is based on the ATTiny 85 and features six I/O pins:

Pin outs:

    • All pins can be used as Digital I/O

    • Pin 0 → I2C SDA, PWM (LED on Model B)
    • Pin 1 → PWM (LED on Model A)
    • Pin 2 → I2C SCK, Analog
    • Pin 3 → Analog In (also used for USB+ when USB is in use)
    • Pin 4 → PWM, Analog (also used for USB- when USB is in use)
    • Pin 5 → Analog In

The ATTiny 85 specs:

  • 8 Bit Data Bus
  • 20 MHz Max Clock Frequency ( w/ external crystal )
  • 8 kB Program Memory Size
  • 2.7 V to 5.5 V Operating Supply Voltage
  • 6 I/O Pins
  • 512 bytes of RAM

Limitations:

Two things you cannot do from the IDE: burn the bootloader and use the serial monitor. Some libraries will work, most will not.  There is no short circuit or reverse polarity protection, so be careful or you will certainly destroy the board, and, if connected via USB (which it really should not be if using external power) the computer could be damaged as well.

SAMPLE IDE OUTPUT

The IDE, as with other Arduino’s, displays the compiler and upload progress in the text area below the coding window.  Several rather bothersome messages can show, but, not to worry, it is normal. See my sample output below.

Sketch uses 668 bytes (11%) of program storage space. Maximum is 6,012 bytes.
Global variables use 9 bytes of dynamic memory.
Running Digispark Uploader…
Plug in device now… (will timeout in 60 seconds)
> Please plug in the device …
> Press CTRL+C to terminate the program.
> Device is found!
connecting: 16% complete
connecting: 22% complete
connecting: 28% complete
connecting: 33% complete
> Device has firmware version 1.6
> Available space for user applications: 6012 bytes
> Suggested sleep time between sending pages: 8ms
> Whole page count: 94  page size: 64
> Erase function sleep duration: 752ms
parsing: 50% complete
> Erasing the memory …
erasing: 55% complete
erasing: 60% complete
erasing: 65% complete
>> Eep! Connection to device lost during erase! Not to worry
>> This happens on some computers – reconnecting…
>> Reconnected! Continuing upload sequence…
> Starting to upload …
writing: 70% complete
writing: 75% complete
writing: 80% complete
> Starting the user app …
running: 100% complete
>> Micronucleus done. Thank you!

Micronucleus is the name of the bootloader.  The disconnect message was a little disturbing, but not a problem.

Maybe I’ll adapt my Battlestar Galactica LCD game to this thing…

Here is a link to the Trinket posts on the blog. It is very similar to the DigiSpark.

digiStump is the maker of the device and they have other products as well. Take a gander around their site. There is a nice Wiki page and forums.

Finally, you can purchase one from Amazon for $4.88 each.  Of course, you can support digiStump by purchasing the device from them, they sell it for $8.95, a little higher than Amazon, but you will be supporting the makers and encourage further development of the product.

Multi-Player Tiny Trek for Arduino

TinyTrekBasicListingWhen I set about creating the Half-Byte Computer/Console, one of the things I, personally, wanted to do with it was create a small, easy to program, micro-micro computer that harkened back to my childhood, otherwise known as the 1970’s.  In order to do so, I needed the language that I learned back then, Tiny Basic, to work on the device.  I did both and it works great.  However, one of my goals with this combo was to play Tiny Trek.

Now, Tiny Trek is small, compared to its big brothers that ran on computers with gobs of memory (you know, 8k) and something called ‘Microsoft Basic’ or ‘Microsoft Basic-80’.  These behemoth Treks’’ would clock in at around 4k to 7k or more. Tiny Trek, however, was small, about 1.5k.

1.5k.

Wow, that’s BIG!  At least, it is when you have less than 1024 bytes (1k) of RAM to work with. 

I am still looking for a solution to the RAM squeeze.

Anyway,  My goal of running Tiny Trek in Tiny Basic is yet to be resolved. HOWEVER…I have decided to code it in Arduino C.  This way, the code can be what ever size it needs and I can have more memory for graphics.  I am also considering making it multiplayer, instead of the computer being the Klingons, one player can be Klingon and one can be the Federation.

Only problem is time, which is in very short supply right now and I’ve got several other things ahead of this, but, I can still plan it out, right?

So…here’s my thoughts on multiplayer Tiny Trek for Arduino.  You won’t need a Half-Byte computer, but if you do….let me know!

Input and Output

11268362_10204228141446944_697530416473282760_oSince this is supposed to be a simulator, I’m thinking we don’t need a full keyboard, so a keypad will work just fine.  I have a few sticky back keypads that I can use. They have 0-9 and a-d and few other keys.  They should work just fine.  I was also thinking of using the Wii Nunchuk, but I am thinking that is overkill and limited in use.  But, I may have dedicated buttons for phaser/photon torpedo and shields up/down.

I’m going to use video and audio, but I am also thinking that a small status display is in order. I have a few 2×16 lcd panels, but they use the serial I/O, which will be used for communication between the two computers, so I may use the little Nokia 5110 LCD’s.  They are similar in resolution to the video, so I could swap screens if needed.  I’m thinking the little screen could show energy, torpedo inventory, shield status and other info.  Video would show the short range/long range display.

Communication

For now, serial will be used to communicate with the two computers.  As each computer will be running independently, I’m thinking code in each version of the game will have to have a main loop that will then monitor communication from the other computer and alert the user accordingly. It also needs to ‘run’ the ships functions and service the UI.  Our snappy 328’s are perfect for this. Oh, it also has to monitor the keypad and update the secondary screen. No problem.

Game

The game, as stated above, will start and run in a loop.  This loop will simply call various functions that will then control the game.  This main loop will:

  • monitor serial i/o
  • update the video
  • monitor the keypad
  • update the secondary screen
  • run each game module
  • do it all over and over until game won or ship is destroyed

The game modules contain the library computer, short and long range scanners, battle mode, navigation, ships condition.

Game Play

Game play will be very similar to the 1970’s version in which you have to seek out and destroy the dreaded Klingons. Instead, however, of having to destroy x number, you have to only get one…but that can be hard as that one is another player who will play unpredictably AND it will be much more difficult to destroy the ships.  There will be only one starbase for the Federation and one for the Klingon.  You must protect your base as it CAN be attacked.  You cannot, however, use phasers or torpedos while ‘docked’.  The Klingon CAN, however, attack while you are docked. Undocking will use one move and you will be vulnerable while doing so.  Klingon bases can cloak for a short time.

Victory is achieved when you destroy your opponent.  You do so by: forcing them to use up all shields and power.  When both are depleted, they will be given the opportunity to surrender. If they do not, you must destroy them. If you do not, they can escape and the game will end in a draw.

Hardware

In addition to the keypads and secondary screens, I’m thinking the PIN 13 LED can be used for the RED ALERT.  It blinks when your opponent is in range.  Some cool things that can be done…the previously mentioned buttons for phaser/photon torpedo control and shield control, there could also be a self destruct (have not thought much about it, though.)  You could get as complicated as you want, provided you have enough pins.

Serial is the best way to talk to the computers, but that does not mean they have to be wired.  There are cheap bluetooth modules that communicate serially and then there is the super cool and super cheap ESP8266 WiFi boards.  And, the best part is that you only need a few lines of code to set them up, no additional libraries are needed.

So, there you go, a multiplayer, interactive Tiny Trek for Arduino.  What do you think? Leave your ideas, suggestions, whatever in the comments below.

Hoping it wont be too long before I can start this. Of course, I need someone to play with…maybe an Internet option too….hmmm….

PS/2 Keyboard and Video Out support for Arduino UNO and compatibles (and the Half-Byte Console)

While this information is readily available on the Internet, I have, nonetheless, received requests on how to do this. The most recent was from Dave in the form of a question on a post about Tiny Basic.  So, I thought I’d write a post-with pictures-on how to connect these things to your UNO or compatible.

PS/2 Keyboard

Connecting the keyboard was a challenge for as I have dsylexia. See! Anyway, I had the hardest time figuring out how to wire up a PS/2 keyboard connector, but, I did and here’s how you can too!

WP_20150315_00_11_58_ProPINOUTS
  • Pin 1 to Pin 5 on chip (ATMEGA 328)
  • Pin 2 to GND
  • Pin 3 to Pin 4 on chip (ATMEGA 328)
  • Pin 5 to +5

Click on the image to see the PS/2 Keyboard connector from the BOTTOM. Pin 1 is on the right, pin 2 above it, pin 3 to the left, pin 4 to the left, pin 5 to the left and pin 6 to the left and down.

VIDEO

Video and mono audio can also be achieved.  Video is generated by soldering two resistors together on one end and then connecting the other ends to different pins on the chip.  Audio imagecomes directly from pin 11 on the 328 chip. Refer to the diagram.  For UNO and compatibles, you will need a 1k Ohm resistor connected to pin 9 for the sync signal and a 470 ohm resistor connected to pin 7 for the video itself. Software controls the actual generation of the signal.  The other ends of the resistors should be soldered together and form the composite video and goes to the center pin of the video connector. The other (or outer) pin of the video connector goes to ground. 

AUDIO

Audio is also generated by software and consists of Atari Pong style beeps.  Connect the center pin of the audio connector to pin 11 of the chip and the ground to the outer shell or other pin of the audio connector.

Libraries

You need the following libraries:

  • TVOUT (Google has announced that they are shutting down google code, so grab this while you can. I do not know where it will end up.)