Wednesday, December 5, 2018

LTE Cellular Shield for Arduino

Ever wanted to turn your Arduino into a phone with LTE technology? Sure, there are lots of 2G and 3G modules out there, but of the few that exist, not many LTE modules for Arduino are well-documented or are insanely expensive! With the SIM7500 shield that's about to change! This shield not only has standard LTE technology with worldwide coverage but it also supports 3G, GPS positioning for asset tracking, and I've also thrown in an I2C temperature sensor in there as well, convenient for at least sending some data to the cloud. You're also not stuck with using 5V Arduino; the shield allows you to configure your own logic voltage so you can interface this with Raspberry Pi and other 3.3V microcontrollers.
Hardware components
Arduino UNO 
Botletics SIM7500 Shield Kit
Hologram Global IoT SIM Card
USB-A to Micro-USB Cable

As a firm believer in great documentation I've set out on a journey to use just about every cellular module I can get my hands on, including theSIM7000module, this SIM7500 project, and hopefully others as well! Join me in this adventure, share your comments, and let's get Arduino users all around the world connected to the cell towers!

The SIM7500 Shield
So what exactly is this project about? Basically it's a "shield" that plugs into an Arduino Uno, Mega, Leonardo, etc. and gives it LTE cellular connectivity, kind of like a phone. You can send and receive text messages, utilize LTE data to send or receive sensor data, use the GPS to track location, call another device just as you would on your phone, and all sorts of other functions that I'm still documenting and unlocking. Below is a quick overview diagram showing the various features of the shield:
Beastly features in a compact shield form factor!


Compatible with Arduino Uno, Arduino Mega, and Arduino Leonardo or practically any 1.8-5V microcontroller if wired externally and set properly (see the shield pinouts in this tutorial)
LTE CAT-1 supporting uplink speed up to 5Mbps, downlink up to 10Mbps
The shield comes in two versions, SIM7500A and SIM7500E (learn how to select a version). Both support 4G LTE, 3G but the SIM7500E also supports 2G and 2.5G fallback
Supports text messaging, voice calling and microphone input
Supports TCP/IP/IPV4/V6 Multi-PDP, MT PDP and FTP/FTPS/HTTP/HTTPS/SMTP/POP3/DNS/MMS
Integrated GNSS/GPS positioning capabilities
MCP9808 High-accuracy I2C temperature sensor with 0.25° typical accuracy
Micro USB for debugging and sending AT commands
SIM7500 module power and network status LEDs
Convenient u.FL antenna connectors for added flexibility
So, first things first: in order to use this module we need to decide which version is most appropriate since the SIM7500 comes in two versions, the SIM7500A and the SIM7500E (probably more versions coming soon). The main differences are the geographical regions in which they operate due to the supported LTE "bands". For more info, please see this Github wiki page on how to select the appropriate version. As you can see, both versions support 3G but the SIM7500E also supports 2.5G and 2G fallback.

Now let's explain some of the features. One cool thing about this shield is that it has both voice input (via an electret microphone) and audio put (speaker) support, unlike my other SIM7000 shield which used the low-bandwidth LTE CAT-M and NB-IoT technologies and voice isn't really feasible or top-notch even if it were done. That means you can call your friend with your Arduino... how cool is that?

Perhaps the most important feature (and probably why you want this shield) is it's LTE data capabilities. Want to make a DIY home security device that takes a picture and sends it to a server? No problem! With this shield you can enable data, do HTTP/HTTPS requests, FTP stuff, and many other cool things that I have yet to explore with you all!

On the software side things are really easy! Just follow these instructions to install the Arduino library (which is an improved version of the Adafruit FONA library) and run the examples!

Goals for This Project
My goal for this project is to share what I've done in creating a powerful shield for Arduino users to cellular-ize (I'll say this with pride) their projects using LTE technology. I'm on a quest to document the latest and greatest cellular modems and make them easy to interface with Arduino and other ubiquitous platforms while providing full documentation!

Keep hacking!

How to make an kitchen timers

This project is made by Angelo Fiorillo.
In the beginning God created the heaven and the earth. And human beings. And human beings created digital kitchen timers, like this one.
And human beings said, Cool but a little dismal. Let's make a better one!

And God said, I heard your call, let there be Arduinos: and there was Arduinos all over the earth, and that was good.

And human beings took an Arduino and created a better kitchen timer, like this one


And God saw the new kitchen timer and said: I saw your new kitchen timer and it looks awful, but it seems too much fun! And that is good. :-)

What you need to have
Now that you know where all this came from, let's go deep into it.

All components I used came from the Arduino Starter Kit, including the small breadboard you see in the pics and in the video. Feel free to accomodate the project into a larger one, if you wish.

You'll need a power source too: while playing around, the PC' USB port and cable will be enough.
Hardware components
Arduino UNO
Adafruit Standard LCD - 16x2 White on Blue
SparkFun Pushbutton switch 12mm
Resistor 10k ohm
Single Turn Potentiometer- 100k ohms
Resistor 221 ohm
Buzzer
Breadboard (generic)

What you need to do
First: please gather all needed components from the Starter Kit or your preferred component bin; if you don't have one, don't panic. There's plenty of on the Internet. You can find the component list below.

And, well, you'll need the code too. It's in its box, below again.

How it works
Basically, like any other similar device you can buy for a buck at any store near you. But this is yours. And this will show you how those little gadgets actually work.

The keyword here is: current mode. The timer itself can run in only one out of four modes at a time:

IDLE - the timer is awaiting for your input, showing the currently set time amount; this is also the initial mode after power up or reset.
SETUP - you can enter this mode by long-pressing S4 (in the code this is called also "reset button"); here, by using S3 ("start stop button"), you can choose which value to change in order to set the elapsed time to be counted down later; finally, using S2 ("down button") and S1 ("up button") respectively, you can decrease or increase the choosen value (hours, minutes or seconds).
RUNNING - You can enter this mode by pressing S3, while leaving it will require both S3 or S4 (which will lead you to IDLE mode).
RINGING - When the desider amount of time is elapsed, this mode is automatically activated; you can leave it (i.e., make the little boy stop ringing) by pressing any switch.
The code
First, we need to include the proper libraries:
#include <LiquidCrystal.h>
#include <TimeLib.h>

If you don't have them already, you'll need to download and install them:

Paul Stoffregen's Time Library
Arduino LiquidCrystal Library
Next, let's initialize that nice LCD module:
Please feel free to scramble the pins at your will in order to obtain a nice wiring layout: don't follow me in this, as I did a terrible wiring plan! :D For instance, you can reverse the latter four pins in the above statement in order to avoid the yellow wires crossing you can see in the schematic below (obviously, you'll have to adjust the button pin constants accordingly, see below). Play, have fun! The life with Arduinos starts right after that copy/paste!

The next 51 code lines contain the static variables declaration and initialization. Please feel free to browse them, their crystal-clear names and some scattered comments will guide you understanding the whole thing.

The setup() function carries out the usual preliminary steps you've seen gazillions of times in any Arduino sketch out there and so far. The only notable statement is the first, which will set the initial LCD display cursor's position. Because, yes: this module requires you to setup a position along its rows and cols and then to "print" something, which will appear starting from that position.

Now let's move to the loop() function.

First of all, let's discover the switch statuses. In order to achieve this, the following code block is used for nearly each of them:

  /*
   * Start/Stop button management
   */
  startStopButtonPressed = false;
  startStopButtonState = digitalRead(startStopButtonPin);
  if(startStopButtonState != startStopButtonPrevState)
  {
    startStopButtonPressed = startStopButtonState == HIGH;
    startStopButtonPrevState = startStopButtonState;
  }

A digitalRead is issued against the related pin and the result is compared to a previously readed value: if something has changed, the new value is stored for future reference and the bool "xxxButtonPressed" static variable is set to true if the button is pressed.

Looking at the circuit diagram below, you'll notice that each input pin is forced to LOW by a 10k resistor unless the corresponding switch is pressed and the pin itself is directly connected to +5V. A fairly classic scenario, uh?

Previously, I said "nearly each of them" because there's one button that acts in a different way than the others: S4. Its code block is capable of detecting the aforementioned long press in order to enter SETUP mode.

Next comes the mode management block switch: each case looks at the button state triggers ("xxxButtonPressed") and redirects the flow toward the proper new state, or performs the proper action.
case MODE_IDLE:
      if(resetButtonPressed)
      {
        Reset();
      }
      if(resetButtonLongPressed)
      {
        currentMode = MODE_SETUP;
      }
      if(startStopButtonPressed)
      {
        currentMode = currentMode == MODE_IDLE ? MODE_RUNNING : MODE_IDLE;
        if(currentMode == MODE_RUNNING)
        {
          // STARTING TIMER!
          startTime = now();
        }
      }
      break;
The previous code snippet shows how the IDLE mode is managed, and it's pretty self-explanatory. Another example shows how any button press while ringing will stop it:
case MODE_RINGING:
      if(resetButtonPressed || startStopButtonPressed || downButtonPressed || upButtonPressed)
      {
        currentMode = MODE_IDLE;
      }
      break;

Looks easy, isn't it? :-) It is.

The next block - "Time management" - performs the actual time difference calculation, triggers the RINGING mode and actually rings the buzz when it's time to do so.

The last block - "LCD management" - manages the LCD display for each mode by printing the proper strings at their proper locations.

That's it.

Wrap up and action!
Now that this little puppy has no more secrets to you, let's see it in action. Thanks for watching, and have fun!






Thursday, November 29, 2018

TB6600 Stepper Motor Driver Review

What is a stepper motor?
Stepper motor is a brushless DC electric motor that divides a full rotation into a number of equal steps The motor's position can then be commanded to move and hold at one of these steps.

How to control a stepper motor?
The fast way to control a stepper motor is just using a stepper motor driver (controller). And TB6600 arduino is just what you need.

TB6600 arduino is an easy-to-use professional stepper motor driver, which could control a two-phase stepping motor. It is compatible with Arduino and other microcontrollers that can output a 5V digital pulse signal. TB6600 arduino stepper motor driver has a wide range power input, 9~42VDC power supply. And it is able to output 4A peak current, which is enough for the most of stepper motors.

The stepper driver supports speed and direction control. You can set its micro step and output current with 6 DIP switch. There are 7 kinds of micro steps (1, 2 / A, 2 / B, 4, 8, 16, 32) and 8 kinds of current control (0.5A, 1A, 1.5A, 2A, 2.5A, 2.8A, 3.0A, 3.5A) in all. And all signal terminals adopt high-speed optocoupler isolation, enhancing its anti-high-frequency interference ability.

As a professional device, it is able to drive 57, 42-type two-phase, four-phase, hybrid stepper motor.

Note: this is a newest upgrade version of TB6600 stepper motor driver.

Thursday, November 1, 2018

Electron Music Box Buzzer

Hardware components
Buzzer
Jumper wires (generic)

Software apps and online services
Github ElectronJS

Story
Hello everybody! I wanted to share my latest creation on Hackster, which is a an app using ElectronJS to play songs on a buzzer using an Arduino! This project was a bit challenging as this is my first attempt at making an Electron app.

ElectronJS is software that allows you to make native apps using JavaScript — which makes it super easy to build a desktop app to work with our Arduino!

Idea Background
This idea came to me as I wanted to make something using a buzzer, as I didn't experiment with buzzers often, so I decided to make something. Then it hit me — why not make an application to play music on it?

I also noticed there is a library of songs that can play songs on a buzzer using Johnny-Five, so why not make an app to control a selection of songs over the Arduino? In fact, why not an Electron app??

And that's when I started making my idea!

Wait wait wait...Electron?
Some people may not be aware as to what ElectronJS is. To put it simply, it's software that enables you to make Native applications using the Blink engine, which is the same engine Google Chrome uses! This allows us to make applications that use HTML, CSS, and JavaScript, and allow it to work with Node.js to work with entire file systems if we want to.

For this project, we're simply making an app that communicates down to our server, which is at the same level as our Arduino.

Setting Up The Application
For this project, it's very simple and very bare. The main objectives of the project were to make a working menu bar app, that communicates via websockets to start and stop the songs playing on the buzzer. Also, the app has to know when a song has finished playing to update the interface so the user knows the song is finished.

Making a menubar application is a big step for someone that's new to ElectronJS, as opposed to making a simple Chrome-based application using a typical window. This in itself was quite challenging, but it's not impossible.

Application Structure
For this project, I set out to fragment the application to work as an app that works with websockets, in order for the commands to be sent down to the server, which was on the same level as the robot's programming.
project 
 ├─-app 
 |   └--index.js 
--config.js 
--index.html 
--main.js  
--robot.js 
In this case, main.js is where all of our Electron's application scripts go. It calls on an index.html file to use as the front end, with app/index.js being the front end's scripting. The robot.js file is used for the Arduino and also the server.

There is also a config file, which is used to store the hostname and port for these files.

Making the Electron Tray
Since this project is merely a menubar app, this is needing some configuration to not only show the window, but also make what is known as a 'tray'.
// Set up Tray and Window variables 
let win; 
let tray; 

// Once the app is ready, make the menu tray and create a new window. 
app.on('ready', () => { 
 makeTray(); 
 makeWindow(); 
}); 

// Store the app's tray icon in a variable — required to make the tray. 
const appIcon = path.join(__dirname, 'static/images/tray-icon.png'); 
const appIconHighlighted = path.join(__dirname, 'static/images/tray-icon-highlight.png'); 

// Build the Tray in our Menubar 
const makeTray = () => { 
 tray = new Tray(appIcon); 
 tray.setToolTip(config.appName); 
 // Toggle the app's window when the tray's icon is clicked 
 tray.on('click', function(event) { 
   toggleWindow(); 
   if (win.isVisible() && process.defaultApp && event.metaKey) { 
     win.openDevTools({ mode: 'detach' }) 
   } 
 }); 
 if (process.platform == 'darwin') { 
   tray.setPressedImage(appIconHighlighted); 
 } 
} 

// Build the App's Window 
const makeWindow = () => { 
 win = new BrowserWindow({ 
   width: 300, 
   height: 570, 
   show: false, 
   frame: false, 
   resizable: false, 
   fullscreen: false, 
   transparent: true, 
   title: config.appName 
 }); 

 // Load the project's HTML file into the app window 
 win.loadURL(`file://${path.join(__dirname, 'index.html')}`); 
 // When the user goes to another app, hide our app 
 win.on('blur', () => { 
   if(!win.webContents.isDevToolsOpened) { 
     win.hide(); 
   } 
 }); 
} 

// Toggle function for the app window 
const toggleWindow = () => { 
 if (win.isVisible()) { 
   win.hide() 
 } else { 
   showWindow(); 
 } 
}
 
// Set positioning for window when it shown (mostly for Mac OS) 
const showWindow = () => { 
 const trayPos = tray.getBounds(); 
 const winPos = win.getBounds(); 
 // set x and y co-ordinate variables to 0 
 let x, y = 0; 
 if (process.platform === 'darwin') { 
   x = Math.round(trayPos.x + (trayPos.width / 2) - (winPos.width / 2)); 
   y = Math.round(trayPos.y + trayPos.height); 
 } 
 win.setPosition(x, y, false); 
 win.show(); 
 win.focus(); 
} 
Using the code above in main.js, the Electron app will make a menubar tray, which, when toggled, will show or hide our application. On MacOS/OS X, this will place our application window directly beneath the centre of our app's tray icon!

One other thing required for the menu tray to work is to show it during an event fired from the ipcRenderer, from our application front end, so under our scripts for app/main.js we send the 'show-window' event once the application's DOM (Document Object Model) has been loaded.
// app/index.js
const { ipcRenderer } = require('electron'); 
document.addEventListener('DOMContentLoaded', () => { 
 // Fire the `show-window` event for the ipc in Electron 
 ipcRenderer.send('show-window'); 
}); 
// main.js
// When the app's file sends the 'show-window' event, run showWindow() 
ipcMain.on('show-window', () => { 
 showWindow(); 
}); 
And now we've got the application running as a menubar application!

Making Our Arduino's Server
In `robot.js`, a server can be made that's exclusively for taking data sent from the application's front end, and vice versa. The idea is to build a server that runs under a specific port, with Websockets running on the server.

const { Board, Piezo, Led } = require('johnny-five'); 
const express = require('express'); 
const { Server } = require('http'); 
const socketIO = require('socket.io'); 
const songs = require('j5-songs'); 

// Import project config 
const config = require('./config'); 

// Set up the socket server 
const app = express(); 
const http = Server(app); 
const io = socketIO.listen(http); 

// Make a new johnny-five Board() instance 
const board = new Board(); 

// Begin the server under the specified port 
http.listen(config.port, () => { 
 console.log(`Server Running under *:${config.port}. Remember to run 'yarn start' to run the app.`); 
}); 

board.on('ready', function() { 
 console.log('board ready'); 

 // Store the Piezo in a constant 
 const buzzer = new Piezo(3); 

 // If the board is connected and is connected to the client, give a handshake. 
 io.on('connect', (client) => { 
   client.on('join', handshake => { 

     io.emit('robot-connected', 'Robot Connected'); 

     // Write the handshake in the terminal console 
     console.log(handshake); 
   });

    // When the app selects a song to play, stop the buzzer playing the current song, then play the selected song.  
   client.on('play-song', (song) => { 
     buzzer.stop(); 
     buzzer.play(songs.load(song), (songEnded) => { 
       if(songEnded) { 
         io.emit('song-ended'); 
       } 
     }); 
   }); 
   
    // If the app selects a song that's already playing, stop the buzzer.  
   client.on('stop-song', () => { 
     buzzer.stop(); 
   }); 
 }); 
}); 
Once the Arduino board is connected, it will wait for the front end to connect and, when successful, will let the front end know the app is connected to the Arduino. It's necessary for the Arduino board to be running alongside the server in order to run the app.

Using Johnny Five and Julian Duque's j5-songs library, sockets can be set up to wait for the front end to press a button, and receive the button's value to play a song on the buzzer. In addition, the server will let the front end know when the song is finished.

// app/index.js
const socketIOClient = require('socket.io-client'); 
// Fetch Config file 
const config = require('../config'); 
// Set up connection to Server Sockets 
const io = socketIOClient(`http://${config.hostName}:${config.port}`);

Another thing to add in the application's front end scripts is to set up the Websockets client, and where the sockets should connect to!

Building The Front End and Making It Communicate
Now that the app and server is running, a front end has to be built using HTML, CSS, and JavaScript. The main part of our HTML is an unordered list that contains a set number of songs for buzzer.


<!-- Playlist application controls --> 
<ul class="playlist app-controls" id="playlist"> 

 <li class="playlist__item"> 
   <div class="playlist__item__label"> 
     <span>Super Mario</span> 
   </div> 

   <div class="playlist__item__button"> 
     <button class="c-button" data-song="mario-fanfare">Play</button> 
   </div> 
 </li> 

 <li class="playlist__item"> 
   <div class="playlist__item__label"> 
     <span>Star Wars</span> 
   </div> 

   <div class="playlist__item__button"> 
     <button class="c-button" data-song="starwars-theme">Play</button> 
   </div> 
 </li> 

 <li class="playlist__item"> 
   <div class="playlist__item__label"> 
     <span>Never Gonna Give You Up</span> 
   </div> 

   <div class="playlist__item__button"> 
     <button class="c-button" data-song="never-gonna-give-you-up">Play</button> 
   </div> 
 </li> 

 <li class="playlist__item"> 
   <div class="playlist__item__label"> 
     <span>Nyan Cat</span> 
   </div> 

   <div class="playlist__item__button"> 
     <button class="c-button" data-song="nyan-melody">Play</button> 
   </div> 
 </li> 

 <li class="playlist__item"> 
   <div class="playlist__item__label"> 
     <span>Tetris</span> 
   </div> 

   <div class="playlist__item__button"> 
     <button class="c-button" data-song="tetris-theme">Play</button> 
   </div> 
 </li> 
</ul> 
<!-- /Playlist application controls --> 
In the button of each item, there's a data attribute called data-song that contains the Song ID of the list item's song, as specified in the Songs table in the j5-songs repository. The value stored in the data-song attribute will be sent to the server so the buzzer knows which song to play!



React and Traffic Lights

A small JavaScript project for controlling and animating a set of LEDs that act like Traffic Lights via a arduino Microcontroller.
React and Johnny-Five Traffic Lights

Hardware components

Arduino UNO
LED (generic)
Resistor 330 ohm
Jumper wires (generic)

Software apps and online services
Johnny-Five

Diagram
The diagram is pretty simple — connect up each arduino  LED to pins 11, 10, and 9, respectively, along with the 220Ohm resistors for each LED. Remember to attach the Ground so the circuit can work! All in all, the circuit is very simple to put together.

Installing
You can use NPM or Yarn to install and use the application, though I recommend yarn, it's pretty good for dependency management.

You can do npm install or yarn install to download all the app's dependencies.

Commands
There are various commands you can use to work the app, from building, to development, to testing. Again, you can use Yarn or NPM to run the app.

List of Commands
start — Start the app Server (note: run build first!)build — Build the app for a production environmentdev-start — Start the app server under the development environmentdev-server — Runs the Webpack development server for the client-side React appstyles — Build the Application styles (uses PostCSS)test — Runs ESlint and Flow to check the code for issues.


Tuesday, October 9, 2018

Wooden Chest Air Quality Monitor

A compact air quality, temperature and humidity monitor enclosed in a small wooden chest, with a four-row LCD display.
Wooden Chest Air Quality Monitor

Hardware components

Arduino UNO & Genuino UNO
DHT11 Temperature & Humidity Sensor

PHPoC Shield for Arduino

Software apps and online services

Arduino IDE

Story



A project completed to measure the air condition in a diesel polluted building. Then the final design enclosed in a wooden box to demonstrate its function to apprentices for inspiration for their projects.
testing sensitivity to fumes using a permanent marker pen


Schematics


Capture off fritzing yxwkogotqw

Code

//***************************************************************************
//  This is a library for the CCS811 air 

//  This sketch reads the sensor

//  Designed specifically to work with the Adafruit CCS811 breakout
//  ----> http://www.adafruit.com/products/3566

 // These sensors use I2C to communicate. The device's I2C address is 0x5A 

#include <SD.h>            // sd card
#include <Wire.h>
#include "RTClib.h"      // real time clock
#include <DHT.h>                                                   // load lib dht11
#include "Adafruit_CCS811.h"
#include "Arduino.h"
#include "LiquidCrystal_PCF8574.h"

#define LCD_ADDRESS 0x27                                       // Define LCD characteristics
#define LCD_ROWS 4
#define LCD_COLUMNS 20
#define SCROLL_DELAY 150
#define BACKLIGHT 255                                         // object initialization
#define dht_apin 2
#define dht_type DHT11

int n = 1;
int val;                                                   // A simple data logger for the Arduino analog pins  

#define LOG_INTERVAL  1000 // mills between entries (reduce to take more/faster data)

                                                      // how many milliseconds before writing the logged data permanently to disk
                                                      // set it to the LOG_INTERVAL to write each time (safest)
                                                      // set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
                                                      // the last 10 reads if power is lost but it uses less power and is much faster!

#define SYNC_INTERVAL 10000 // mills between calls to flush() - to write data to the card 600000 = 10 minutes
uint32_t syncTime = 0; // time of last sync()


RTC_DS1307 RTC;                                         // define the Real Time Clock object


const int chipSelect = 10;                             // for the data logging shield, we use digital pin 10 for the SD cs line


DHT dht(dht_apin, dht_type);                          // sensor pin S to pin11

LiquidCrystal_PCF8574 lcdI2C;
Adafruit_CCS811 ccs;


File logfile;

void error(char *str)
{
  Serial.print(F("error: "));
  Serial.println(str);
}


void setup() {

 Serial.begin(9600);

  // initialize the SD card
  Serial.print(F("Initializing SD card..."));
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    error("Card failed, or not present");
  }
  Serial.println(F("card initialized."));
  
  // create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
  }
  
  if (! logfile) {
    error("couldnt create file");
  }
  
  Serial.print(F("Logging to: "));
  Serial.println(filename);

  // connect to RTC
  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
#if ECHO_TO_SERIAL
    Serial.println(F("RTC failed"));
#endif  //ECHO_TO_SERIAL
  }
  

  logfile.println("datetime,co2  ,tvoc  ,Humidity  ,Temperature ");    
//#if ECHO_TO_SERIAL
//  Serial.println("..........,......,datetime,.....,......,......");
//#endif //ECHO_TO_SERIAL
 
  // If you want to set the aref to something other than 5v
  analogReference(EXTERNAL);
  lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT); 
  Serial.println(F("CCS811 test"));
  lcdI2C.print("     CCS811 test" );
  lcdI2C.setCursor (0,1); 
  lcdI2C.print("     warming up" );
  lcdI2C.setCursor (0,2);
  lcdI2C.print("data logger file No." );
  lcdI2C.setCursor (0,3);
  lcdI2C.println(filename);
  if(!ccs.begin()){
  Serial.println(F("Failed to start sensor! Please check your wiring."));
  while(1);
  }
  //calibrate temperature sensor
  while(!ccs.available());
  float temp = ccs.calculateTemperature();
  ccs.setTempOffset(temp - 25.0);

 delay(10000);                       // wait for 10 seconds
   lcdI2C.clear();                          // Clear LCD screen.
  
}

void loop() {
    float h = dht.readHumidity();
    float f = dht.readTemperature();
    if(ccs.available()){
    float temp = ccs.calculateTemperature();
    if(!ccs.readData()){
     
DateTime now;
 
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));   // delay for the amount of time we want between readings
   
  now = RTC.now();  // fetch the time

 int H = now.hour(); // Get the hours right now and store them in an integer called h
 int M = now.minute(); // Get the minutes right now and store them in an integer called m
 int S = now.second(); // Get the seconds right now and store them in an integer called s
  
  logfile.print(now.year(), DEC);
  logfile.print("/");
  logfile.print(now.month(), DEC);
  logfile.print("/");
  logfile.print(now.day(), DEC);
  logfile.print(" ");
  if (H<10){   // Add a zero, if necessary, as above
  logfile.print(0);
 }
  logfile.print(now.hour(), DEC);
  logfile.print(":");
  if (M<10){   // Add a zero, if necessary, as above
  logfile.print(0);
 }
  logfile.print(now.minute(), DEC);
  logfile.print(":");
  if (S<10){   // Add a zero, if necessary, as above
  logfile.print(0);
 }
  logfile.print(now.second(), DEC);
  logfile.print('"');
  Serial.print('"');
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  if (H<10){   // Add a zero, if necessary, as above
  Serial.print(0);
 }
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  if (M<10){   // Add a zero, if necessary, as above
  Serial.print(0);
 }
  Serial.print(now.minute(), DEC);
  Serial.print(F(":"));
  if (S<10){   // Add a zero, if necessary, as above
  Serial.print(0);
 }
  Serial.print(now.second(), DEC);
  Serial.print(F("    "));
  Serial.print(F("CO2: "));
  Serial.print(ccs.geteCO2());
  Serial.print(F("ppm, TVOC: "));
  Serial.print(ccs.getTVOC());
  Serial.print(F("ppb   Temp:"));
  Serial.println(f);                          // temp from dht11
    
    
    lcdI2C.setCursor (0,0);  
    lcdI2C.print ("CO2  ");  
    lcdI2C.setCursor (5,0);  
    lcdI2C.print ("       ");
    lcdI2C.setCursor (5,0); 
    lcdI2C.print(ccs.geteCO2());              // Print print String to LCD on first line
    lcdI2C.setCursor (0,1);                    // Set cursor at the begining of line 2
    lcdI2C.print ("tVOC ");
    lcdI2C.print(ccs.getTVOC());          // Print print String to LCD on second line
    lcdI2C.print ("     ");
    lcdI2C.setCursor (12,1); 
    if (H<10){   // Add a zero, if necessary, as above
    lcdI2C.print(0);
    }
    lcdI2C.print(now.hour(), DEC);
    lcdI2C.print (":");
    if (M<10){   // Add a zero, if necessary, as above
    lcdI2C.print(0);
 }
    lcdI2C.print(now.minute(), DEC);
    lcdI2C.print (":");
    if (S<10){   // Add a zero, if necessary, as above
    lcdI2C.print(0);
 }
   lcdI2C.print(now.second(), DEC); 
   lcdI2C.setCursor (0,2);  
   lcdI2C.print ("Humidity    ="); // print on the lcd Humidity = 
   lcdI2C.print(h); // to print the humidity
   lcdI2C.print("% "); //print "percentage" symbol
   lcdI2C.setCursor (0,3); 
   lcdI2C.print("Temperature ="); // print on the lcd temp = 
   lcdI2C.print (f); // print on the lcd temperture
   lcdI2C.print((char)223); // print "degrees" symbol 
   lcdI2C.print("C"); // print "C" with spaces after to fill 20 character line

  
  logfile.print(", ");    
  logfile.print(ccs.geteCO2());
  logfile.print(",");    
  logfile.print(ccs.getTVOC());
  logfile.print(",");
  logfile.print(h);
  logfile.print(",");
  logfile.print(f);
  logfile.println();


  
  // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
  // which uses a bunch of power and takes time
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();
  
  // blink LED to show we are syncing data to the card & updating FAT!
 
  logfile.flush();


    
    }
    else{
      Serial.println(F("ERROR!"));
      while(1);
    }
  }
 
}