Tag Archives: Hackster

Arduino-Based Two-Way Pager

This Arduino-based pager by  Mike Schaus will allow you to send and receive real SMS text messages. This messaging device has its own SIM card and phone number.

In order to build this project you need the following parts:

And you will need to use this software to run the project: Hologram Data Router.

This project was made possible as part of Hologram’s Hacker-In-Residence program, The Hologram Global SIM Card allows you to connect you IoT device everywhere. Paired with a powerful device management platform and API. It provides a cellular data service that works with any device that accepts a SIM card. In addition it is totally inexpensive.

GSM shield, the Hologram things, and Arduino stacked on top of each other made a good combination to build such a project. For powering the project, Mike had used a 9V battery as an option, and still, powering from USB is possible.

Mike had designed this project so it could be used by children instead of a real cell phone, or it could be used as an “SOS” button for someone working alone outdoors or even exercising.

Check this video to know how this project works:

The amazing thing about Adafruit LCD shield that it only uses 2 pins of Arduino since it works over the I2C bus, which results with many places left for future features.

This is the schematics of the project: It is super easy, the wires mean putting the pieces on top of each other.

And here is the Arduino code used:

#include <GSM.h>

#define PINNUMBER ""

// include the LCD library code:
#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>

// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

// These #defines make it easy to set the backlight color
#define OFF 0x0
#define ON 0x1

// make the arrow special character on the LCD
const byte arrow[8] =
{
 B00000, B00000, B01000, B01100, B01110, B01100, B01000, B00000
};

// initialize the GSM library instance
GSM gsmAccess(false); // include a 'true' parameter for debug enabled
GSM_SMS sms;

// char array of the telephone number to send SMS
// change the number 12125551212 to a number
// you have access to
char remoteNumber[20]= "12125551212";

// Array to hold the number a SMS is retreived from
char senderNumber[20];

// char array of the possible outgoing messages to choose from the menu
char* responses[]={"Mike=Awesome!", "Yes", "No", "Howdy!"};
//#define NUMRESPONSES 4 // if someone knows how to calculate this instead, I'm all ears
#define NUMRESPONSES (sizeof(responses)/sizeof(char *)) // thanks to Steve Kemp's comment!

int position=-1; // this way the first button press will always show first option of the menu

int inByte = 0; // incoming serial byte for keyboard interface

boolean backlight = true; // track backlight status for toggling

unsigned long previousMillis = 0; // will store last time messages were checked
#define CHECKINTERVAL 1500 // how often to check for text messages

void setup() {
  // put your setup code here, to run once:

  // initialize serial communications
  Serial.begin(9600);
  Serial.println(F("SMS Message Sender -- starting up..."));

  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);

  // Print a message to the LCD
  lcd.print(F("Hello, Hologram!"));
  lcd.setCursor(0, 1);
  lcd.print(F("Starting up..."));
  lcd.setBacklight(ON);

  // set up the arrow character for display
  lcd.createChar(0, arrow);

  // connection state
  boolean notConnected = true;

  // Start GSM shield
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  while(notConnected)
  {
    if(gsmAccess.begin(PINNUMBER)==GSM_READY) {
      notConnected = false;
      Serial.println(F("GSM is connected because you are so awesome"));
      Serial.println(F("Waiting for messages, or send with \"s\""));
      Serial.println();

      lcd.clear();
      lcd.setCursor(0,0);
      homeScreen();

    }
    else
    {
      Serial.println(F("Not connected"));
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(F("Not connected"));
      delay(1000);
    }
  }
}

// this is the menu system function
void showResponses() {
//  Serial.println(position); // only for debugging menu system

  lcd.clear();
  lcd.setCursor(0,0);
  
  // make sure cursor position is legal
  if (position<0) position=0;
  if (position>NUMRESPONSES-1) position = NUMRESPONSES-1;

  // write current selection and next option if there is another option
  lcd.write(0); //arrow character
  lcd.print(position+1);
  lcd.print("-");
  lcd.print(responses[position]);
  if (position < NUMRESPONSES-1) {
    lcd.setCursor(0,1);
    lcd.print(" ");
    lcd.print(position+2);
    lcd.print("-");
    lcd.print(responses[position+1]);
  }
}


void homeScreen() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("SMS Messenger!");
  lcd.setCursor(0,1);
  lcd.print("Ready; up/dn snd");

  position=-1; //reset response selection
}


void receiveSMS(){
  
  char c;

  // If there are any SMSs available()
  if (sms.available()) {
    Serial.println("Message received from:");

    // Get remote number
    sms.remoteNumber(senderNumber, 20);
    Serial.println(senderNumber);

    lcd.clear();
    lcd.setCursor(0,0);
    backlight = true;
    lcd.setBacklight(ON);

    // An example of message disposal
    // Any messages starting with # should be discarded
    if (sms.peek() == '#') {
      Serial.println("Discarded SMS");
      sms.flush();
    }

    // Read message bytes and print them
    // because sms.read only returns one character at a time
    int i=0;
    while (c = sms.read()) {
      i++;
      Serial.print(c);
      if (i==17) lcd.setCursor(0, 1); // move to next line if needed
      if (i<33) lcd.print(c); // don't try to print more than 32 chars just in case
    }

    Serial.println("\nEND OF MESSAGE");

    // Delete message from modem memory
    sms.flush();
    Serial.println("MESSAGE DELETED");
    Serial.println();

    // wait for right button to acknowlege before letting program continue
    boolean acknowledged = false;
    while(!acknowledged) {
      uint8_t buttons = lcd.readButtons();
      if (buttons & BUTTON_RIGHT) acknowledged = true;
      delay(50); //short delay for troubleshooting -- without this it behaves strangely
    }
    homeScreen();
    delay(400); // prevent multiple presses in a row
  }
}

// function to show message options in the serial monitor
void printResponseOptions(){
  for(int i=0; i<NUMRESPONSES; i++){
    Serial.print(i);
    Serial.print("-");
    Serial.println(responses[i]);
  }
  Serial.println();
}


void sendSMS(const char* txtMsg){

  Serial.print("Message to mobile number: ");
  Serial.println(remoteNumber);

  // print sms text info
  Serial.println("SENDING");
  Serial.println("Message:");
  Serial.println(txtMsg);

  // send the message
  sms.beginSMS(remoteNumber);
  sms.print(txtMsg);
  // next, add a signature to the chosen message
  sms.print(" --Be sure to connect with me on my blog http://mschausprojects.blogspot.com");
  // call endSMS function to finish sending; it will return 1 if successful
  if (sms.endSMS()==1) {
    Serial.println("\nCOMPLETE!\n");
    homeScreen();
  }
  else {
    Serial.println("\nERROR\n");
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("error");
  }
  Serial.println();
}



void loop() {
  // put your main code here, to run repeatedly:

  uint8_t buttons = lcd.readButtons();

  if (buttons) {
    if (buttons & BUTTON_UP) {
      position--;
      showResponses();
      backlight = true;
      lcd.setBacklight(ON);
    }
    if (buttons & BUTTON_DOWN) {
      position++;
      showResponses();
      backlight = true;
      lcd.setBacklight(ON);
    }
    if (buttons & BUTTON_LEFT) {
      homeScreen();
      backlight = true;
      lcd.setBacklight(ON);
    }
    if (buttons & BUTTON_RIGHT) {
      backlight = !backlight; // toggle the backlight state
      if (backlight) lcd.setBacklight(ON);
      else lcd.setBacklight(OFF);
      homeScreen(); // have to write to screen after turning light off, otherwise it goes blank
    }
    if (buttons & BUTTON_SELECT) {
      // make sure cursor selected position is legal
      if (position<0) position=0;
      
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Sending...");
      lcd.setCursor(0,1);
      lcd.print(responses[position]);
      backlight = true;
      lcd.setBacklight(ON);
      sendSMS(responses[position]);
    }
    delay(200); // prevent multiple presses in a row
  }


  // this is for serial interface only, not related to LCD and buttons
  // send a message when I type "s" in serial monitor
  // then wait for my selection of the response number
  if (Serial.available() > 0) {
    inByte = Serial.read(); // get incoming byte
    if (inByte == 's') {
      printResponseOptions();

      while (Serial.available() > 0) {  // clear the keyboard buffer just in case
        char junk = Serial.read();
      }
  
      while (Serial.available() == 0) ;  // Wait here until input buffer has a character
      inByte = Serial.parseInt();
      // would want to check for valid choice here to be more robust
      sendSMS(responses[inByte]);
    }
  }

  // check for new messages only once every few seconds to keep interface more responsive
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= CHECKINTERVAL) {
    previousMillis = currentMillis;
    receiveSMS(); // takes about 26ms when there are no messages
  }
}
CREDITS

R3tkcxkom1pu38aqb0bh

More details about this project are available on hackster.io and Mike’s own blog post. You can learn more about his projects on the same blog.

IdIoTware SD Card Temperature Logger

In this tutorial at hackster.io you will learn how to log data from LM35 temperature sensor values to an SD card and store it as CSV file.

In order to build this project you need the following parts:

  1. Arduino UNO
  2. idIoTware Shield
  3. USB-A to B Cable
  4. SD Card (up to 8GB)
  5. 2x Generic Jumper (0.1″)

 

The Idiotware Shield is a learning platform that offers both novices and advanced Arduino users
the opportunity to bring hundreds of projects to life quickly. it offers a large variety of wireless communication options, input sensors, outputs, storage and device extensibility.

 

The idIoTware shield has a built in lm35 sensor that has a sensitivity of 10mV / oC, that means according to this equation: Temperature ( oC) = Vout * (100 oC/V)

That if Vout is 0.5V , then, Temperature = 50 oC. However, this built-in sensor gives a higher analog voltage on pin A0 if a higher temperature was applied.

To set up the IdIoTware shield you need to connect  LM35 sensor to SEL0 3 pin header by using a jumper. The SD card should be connected to D6 and SD pin header, thus we need antoher jumper to enable it.
By uploading this code to your Arduino, you will create a CSV file with every one minute for 15 minutes. The temperature will be logged to the file thanks to the SdFat library used. You can edit the rate and duration as you prefer.

/* 
 The circuit:
 * LM35 sensor on analog pin A3
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 */

#include <SPI.h>
#include <SdFat.h>
SdFat sd;
const uint8_t chipSelect = 6;

//const int chipSelect = 4;   //cs pin of SD card shield
int tempPin = A3;      // LM 35 is connected to A3 pin.
int buzzerPin = A2;    // buzzer is connected to A2 pin

File dataFile;   // the logging file
char filename[] = "Temp000.CSV";
float tempInCelcius;
float tempInFarenheit;
unsigned long time=0;
int samplingTime = 10;  //this variable is interval(in Seconds) at which you want to log the data to SD card.
int duration = 15;     //this variable is duration(in Minutes) which is the total time for which you want to log data.


void setup() 
    {
      // Open serial communications and wait for port to open:
      Serial.begin(9600);
      while (!Serial)
          {
            ; // wait for serial port to connect. Needed for native USB port only
          }

      Serial.print("Initializing SD card...");

     // see if the card is present and can be initialized:
     if (!sd.begin(chipSelect))  
        { sd.initErrorHalt();
          Serial.println("Card failed, or not present");
          // don't do anything more:
          return;
        }
     Serial.println("card initialized.");

     // create a new file
     for(unsigned int i = 0; i < 1000; i++) 
        {
          filename[4] = i/100 + '0';
          filename[5] = ((i%100)/10) + '0';
          filename[6] = i%10 + '0';
          if(! sd.exists(filename)) 
            {
              // only open a new file if it doesn't exist
              dataFile = sd.open(filename, FILE_WRITE);
              break;  // leave the loop!
            }
        }

      if(! dataFile) 
        { //alert user
          Serial.println("couldnt create file");
          int alertAlarm1[] = { 1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,
                           1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,};
          int noteDurations[] = { 5,5,5,5,5,5,5,5,5,5,5,
                                  5,5,5,5,5,5,5,5,5,5,5 };
          for (int thisNote = 0; thisNote < 20; thisNote++) 
             {
               // Duration = 1 second / note type
               // e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
               int noteDuration = 2500 / noteDurations[thisNote];
               tone(A2,alertAlarm1[thisNote], noteDuration);
               //pause for the note's duration plus 100 ms:
               delay(noteDuration + 100);
             }
        }

     Serial.print("Logging to: ");
     Serial.println(filename);
     
     dataFile = sd.open(filename, FILE_WRITE);
     // if the file is available, write to it:
     if (dataFile) 
       { 
         dataFile.print("Logging Temperature for ");
         dataFile.print(duration);
         dataFile.print(" minutes at interval of ");
         dataFile.print(samplingTime);
         dataFile.println(" seconds.");
         
         dataFile.close();
       }
      // check availble space on SD Card
      uint32_t freeKB = sd.vol()->freeClusterCount();
      freeKB *= sd.vol()->blocksPerCluster()/2;
      Serial.print("Free space KB: ");
      Serial.println(freeKB);
      uint32_t freeMB= freeKB/1024;
      Serial.print("Free space in MB: ");
      Serial.println(freeMB); 
      
      if(freeKB <= 500)
        {
          Serial.println("LOW SPACE!!!");
          int alertAlarm2[] = { 1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,
                               1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000};
          int noteDurations[] = { 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
                                  15,15,15,15,15,15,15,15,15,15,15,15,15,15,15  };
          for (int thisNote = 0; thisNote < 20; thisNote++) 
             {
               // Duration = 1 second / note type
               // e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
               int noteDuration = 2500 / noteDurations[thisNote];
               tone(A2,alertAlarm2[thisNote], noteDuration);
               //pause for the note's duration plus 50 ms:
               delay(noteDuration + 50);
             }
        }
     duration *= 60;   //convert durartion in minutes to seconds   
   }

void loop() 
    {
      dataSamples();    // here we are logging data at interval of 1 minute for 15 mintutes, i.e, 15 samples.
                            // if you want to save data for 2 hours then simply multiply 2 by 60 which will give 
                            // you value of 120 minutes then use 120 as second parameter.
    }

// this method will log data to SD card at particular interval and for paricular duration
int dataSamples()
   { 
     // here we are logging data at interval of 1 minute for 15 mintutes, i.e, 15 samples.
     // if you want to save data for 2 hours then simply multiply 2 by 60 which will give 
     // you value of 120 minutes then change the varible duration to 120. 

      tempInCelcius = ( 5.0 * analogRead(tempPin) * 100.0) / 1024.0;
      
      // uncomment following line to get temperature values in Farehniet
      //tempInFarenheit = ((tempC*9)/5) + 32;            //convert celcius to farenheit
      
      unsigned long  elapsedTime = millis()/1000;   // this variable will keep track of elapsed time
      while(((millis()/1000)-elapsedTime) < 1);    // this loop will do nothing until a second has passed 
      time++;                                       //increment time after each second.
 
      if((duration >= time) && (time % samplingTime == 0))
        {
          LogToSDcard();  //Log to SD using commands under void LogToSD()  
          // print to the serial port too:              
          Serial.print("Temperature: ");
          Serial.print(tempInCelcius);
          Serial.print(char(176)); 
          Serial.println("C");     
        }
           
   }
   
void LogToSDcard()
   {
     // open the file. note that only one file can be open at a time,
     // so you have to close this one before opening another.
     dataFile = sd.open(filename, FILE_WRITE);
     // if the file is available, write to it:
     if (dataFile) 
       { 
         dataFile.print(tempInCelcius);   
         dataFile.println("°C");
         dataFile.println(",");
         dataFile.close();
         
     // to print temperature values in Farehniet uncomment following code.    
         
      /*  dataFile.print(tempInFarenheit);
         dataFile.print("°C");
         dataFile.println(",");
         dataFile.close();   */
       } 
  
      //if the file isn't open, pop up an error:
     else 
        {
          Serial.println("error opening datalog.txt");
          delay(2000);
        }
   }   
 

As soon you get the CSV file copied from the SD card, you can visualize the data in graphs.

This video by IdIoTware team demonstrates how to build this project in details, check it out:

You can check the project’s page for more information and detailed tutorial.

 

Controlling A Robotic Arm By Gestures Using Kinect Sensor & Arduino

B.Avinash and J.Karthikeyan had developed a robotic arm that mimic their moves using a Kinect sensor with MATLAB Simulink and an Arduino. The arm was built based on servo motors that replicate the right arm shoulder, elbow and hand movements.

college-project-final-year-2016-9

ic568992The Kinect sensor is a horizontal bar of motion sensing input devices which enable users to control and interact with their computers through a natural user interface using gestures and spoken commands.

The sensor consists of a RGB camera, depth sensor, and multi-array microphone running proprietary software. It provides full-body 3D motion capture, facial recognition, and voice recognition capabilities.

MATLAB Simulink is a graphical programming environment for modeling, simulating and analyzing multidomain dynamic systems. It supports simulation, automatic code generation, and continuous test and verification of embedded systems.

Simulink is developed by Mathworks, and it offers integration with MATLAB environment, enabling developers to incorporate MATLAB algorithms into models and export simulation results for further analysis. Simulink is widely used in automatic control and digital signal processing for multidomain simulation and Model-Based Design.

To build a similar gesture-controlled arm you need these components:

Thanks to Simulink support for Kinect, the computer collects data from the connected kinect device and translates them into servo angles in MATLAB. These angles are sent to the servos through the arduino via TTL device, resulting movement of the arm with a slight delay.

TTL - Arduino & Arduino - Servo Connection Schematic
TTL – Arduino & Arduino – Servo Connection Schematic
Simulink Model
Simulink Model

This project has been chosen in the week’s (29/10/2016) Pick of the Week during Matlab Simulink Hardware Challenge 2016, and it also had won the 4th place in “MATLAB International Simulink Hardware Challenge 2016“.

Arduino code, other files and resources are reachable at this instructable and this hackster.io page.