Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Hand tools and fabrication machines | ||||||
|
Do you also hate it when your train is late, or if you have to stand for hours in a crowded carriage, or if the remaining time on the arrival board isn't correct? We have the solution! Our concept is to develop the train of the future.
The train:
In every station, one or more carriages will be standing. Every carriage has a motor. When a train is approaching to the station. The first carriage will unlink and go to the side track. The other carriages will go straight on.
In the meantime, a carriage with passengers will leave the station. When this carriage is in front of the train, the carriage with passengers will link to the other carriages. The train is now moving to the next station.
We have realized this with a Lego NXT robot and 3D printed wheels.
GPS:
In the train, there will be a GPS. This will give the passengers in the station up-to-date information by a mobile application.
We used an IOTOPIA rapid development kit for this part of our project.
Reservation system:
We have also build a reservation system. This will prevent crowded trains. When you buy your train tickets online, you receive a password. You need to enter this password at the entrance of the train to get access to the train.
We have build the access system with an Arduino prototype shield V2, some push buttons and resistors.
Extra: Lego bricks:
This are the bricks that we have used to build our project. They are all part of the LEGO NXT set.
Project video:
To help you understand our project, we have made a short video to explain it.
End
If you have any further questions. Please ask them below in the comments.
Thank you for watching to our project,
Tom - Stijn - Thijs
#include "ATT_IOT_UART.h" // AllThingsTalk Arduino UART IoT library
#include <SPI.h> // Required to have support for signed/unsigned long type
#include "keys.h" // Keep all your personal account information in a seperate file
#include <SoftwareSerial.h>
ATTDevice Device(&Serial1);
char httpServer[] = "api.smartliving.io"; // HTTP API Server host
char mqttServer[] = "broker.smartliving.io"; // MQTT Server Address
// Define PIN numbers for assets
// For digital and analog sensors, we recommend to use the physical pin id as the asset id
// For other sensors (I2C and UART), you can select any unique number as the asset id
#define gpsId 2 // Digital sensor is connected to pin D2 on grove shield
SoftwareSerial SoftSerial(2, 3);
unsigned char buffer[64]; // Buffer array for data receive over serial port
int count=0;
int time= 30; // set time between reading coordinates (in seconds)
// Required for the device
void callback(int pin, String& value);
void setup()
{
Serial.begin(57600); // Init serial link for debugging
while(!Serial && millis() < 1000); // Make sure you see all output on the monitor. After 1 sec, it will skip this step, so that the board can also work without being connected to a pc
Serial.println("Starting sketch");
Serial1.begin(115200); // Init serial link for WiFi module
while(!Serial1);
while(!Device.StartWifi())
Serial.println("Retrying...");
while(!Device.Init(DEVICEID, CLIENTID, CLIENTKEY)) // If we can't succeed to initialize and set the device credentials, there is no point to continue
Serial.println("Retrying...");
while(!Device.Connect(httpServer)) // Connect the device with the AllThingsTalk IOT developer cloud. No point to continue if we can't succeed at this
Serial.println("Retrying");
Device.AddAsset(gpsId, "GPS module", "GPS", false, "{\"type\": \"object\",\"properties\": {\"lat\": {\"type\": \"number\", \"unit\": \"°\"},\"lng\": {\"type\": \"number\", \"unit\": \"°\"},\"alt\": {\"type\": \"number\", \"unit\": \"°\"},\"time\": {\"type\": \"integer\", \"unit\": \"epoc time\"}},\"required\": [\"lat\",\"lng\",\"alt\",\"time\" ]}"); // Create the sensor asset for your device
delay(1000); // Give the WiFi some time to finish everything
while(!Device.Subscribe(mqttServer, callback)) // Make sure that we can receive message from the AllThingsTalk IOT developer cloud (MQTT). This stops the http connection
Serial.println("Retrying");
//pinMode(gpsId, INPUT); // Initialize the digital pin as an input.
SoftSerial.begin(9600); // the SoftSerial baud rate
Serial.println("GPS module is ready for use!");
delay(2000);
}
float longitude;
float latitude;
float altitude;
float timestamp;
float timestamp1;
float longitude1;
float latitude1;
float distance;
float time_left;
float station = 15.81;
void loop()
{
if(readCoordinates() == true)
{
delay(time*1000);
if(readCoordinates1() == true)SendValue();
}
Device.Process();
delay(5000);
}
void SendValue()
{
float distance = acos(sin(latitude*3.141592654/180)*sin(latitude1*3.141592654/180)+cos(latitude1*3.141592654/180)*cos(latitude*3.141592654/180)*cos(abs(longitude*3.141592654/180-longitude*3.141592654/180)))*6370*1000;
float Speed = distance/ time*3600;
Serial.println(sin(latitude*3.141592654/180)*sin(latitude1*3.141592654/180)+cos(latitude1*3.141592654/180)*cos(latitude*3.141592654/180)*cos(abs((longitude*3.141592654/180)-(longitude1*3.141592654/180))),20);
float time_left = station / Speed ;
Serial.print("sending gps data");
String data;
data = "{\"Distance\":" + String(distance, 10)+"km" + ",\"Speed\":" + String(Speed, 3)+"km/h" + ",\"Time left\":" + String(time_left, 3)+"h" + "}";
Device.Send(data, gpsId);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Callback function: handles messages that were sent from the iot platform to this device.
void callback(int pin, String& value)
{
Serial.print("incoming data for: "); // Display the value that arrived from the AllThingsTalk IOT developer cloud.
Serial.print(pin);
Serial.print(", value: ");
Serial.println(value);
}
bool readCoordinates()
{
bool foundGPGGA = false; // Sensor can return multiple types of data, need to capture lines that start with $GPGGA
if (SoftSerial.available()) // If date is coming from software serial port ==> data is coming from SoftSerial shield
{
while(SoftSerial.available()) // Reading data into char array
{
buffer[count++]=SoftSerial.read(); // Writing data into array
if(count == 64)break;
}
foundGPGGA = count > 60 && ExtractValues(); // If we have less then 60 characters, then we have bogus input, so don't try to parse it or process the values
clearBufferArray(); // Call clearBufferArray function to clear the stored data from the array
count = 0;
}
return foundGPGGA;
}
bool ExtractValues()
{
unsigned char start = count;
while(buffer[start] != '$') // Find the start of the GPS data -> multiple $GPGGA can appear in 1 line, if so, need to take the last one.
{
if(start == 0) break; // It's an unsigned char, so we can't check on <= 0
start--;
}
start++; // Remove the '$', don't need to compare with that.
if(start + 4 < 64 && buffer[start] == 'G' && buffer[start+1] == 'P' && buffer[start+2] == 'G' && buffer[start+3] == 'G' && buffer[start+4] == 'A') //we found the correct line, so extract the values.
{
start+=6;
timestamp = ExtractValue(start);
latitude = ConvertDegrees(ExtractValue(start) / 100);
start = Skip(start);
longitude = ConvertDegrees(ExtractValue(start) / 100);
start = Skip(start);
start = Skip(start);
start = Skip(start);
start = Skip(start);
altitude = ExtractValue(start);
return true;
}
else
return false;
}
float ExtractValue(unsigned char& start)
{
unsigned char end = start + 1;
while(end < count && buffer[end] != ',') // Find the start of the GPS data -> multiple $GPGGA can appear in 1 line, if so, need to take the last one.
end++;
buffer[end] = 0; // End the string, so we can create a string object from the sub string -> easy to convert to float.
float result = 0.0;
if(end != start + 1) // If we only found a ',', then there is no value.
result = String((const char*)(buffer + start)).toFloat();
start = end + 1;
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool readCoordinates1()
{
bool foundGPGGA1 = false; // Sensor can return multiple types of data, need to capture lines that start with $GPGGA
if (SoftSerial.available()) // If date is coming from software serial port ==> data is coming from SoftSerial shield
{
while(SoftSerial.available()) // Reading data into char array
{
buffer[count++]=SoftSerial.read(); // Writing data into array
if(count == 64)break;
}
foundGPGGA1 = count > 60 && ExtractValues1(); // If we have less then 60 characters, then we have bogus input, so don't try to parse it or process the values
clearBufferArray(); // Call clearBufferArray function to clear the stored data from the array
count = 0;
}
return foundGPGGA1;
}
bool ExtractValues1()
{
unsigned char start = count;
while(buffer[start] != '$') // Find the start of the GPS data -> multiple $GPGGA can appear in 1 line, if so, need to take the last one.
{
if(start == 0) break; // It's an unsigned char, so we can't check on <= 0
start--;
}
start++; // Remove the '$', don't need to compare with that.
if(start + 4 < 64 && buffer[start] == 'G' && buffer[start+1] == 'P' && buffer[start+2] == 'G' && buffer[start+3] == 'G' && buffer[start+4] == 'A') //we found the correct line, so extract the values.
{
start+=6;
timestamp1 = ExtractValue(start);
latitude1 = ConvertDegrees(ExtractValue1(start) / 100);
start = Skip(start);
longitude1 = ConvertDegrees(ExtractValue1(start) / 100);
start = Skip(start);
start = Skip(start);
start = Skip(start);
start = Skip(start);
altitude = ExtractValue1(start);
return true;
}
else
return false;
}
float ExtractValue1(unsigned char& start)
{
unsigned char end = start + 1;
while(end < count && buffer[end] != ',') // Find the start of the GPS data -> multiple $GPGGA can appear in 1 line, if so, need to take the last one.
end++;
buffer[end] = 0; // End the string, so we can create a string object from the sub string -> easy to convert to float.
float result = 0.0;
if(end != start + 1) // If we only found a ',', then there is no value.
result = String((const char*)(buffer + start)).toFloat();
start = end + 1;
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float ConvertDegrees(float input)
{
float fractional = input - (int)input;
return (int)input + (fractional / 60.0) * 100.0;
}
unsigned char Skip(unsigned char start)
{
unsigned char end = start + 1;
while(end < count && buffer[end] != ',') // Find the start of the GPS data -> multiple $GPGGA can appear in 1 line, if so, need to take the last one.
end++;
return end+1;
}
void clearBufferArray() // Function to clear buffer array
{
for (int i=0; i<count; i++)
{
buffer[i] = NULL; // Clear all index of array with command NULL
}
}
GPS CODE - keys.h
Arduino#ifndef SETTINGS
#define SETTINGS
#define DEVICEID "******" // Your device id comes here
#define CLIENTID "*****" // Your client id comes here;
#define CLIENTKEY "*****" // Your client key comes here;
#endif
/*
DigitalReadSerial
Reads a digital input on pin 2, prints the result to the serial monitor
This example code is in the public domain.
*/
// digital pin 2 has a pushbutton attached to it. Give it a name:
int pushButton1 = 13;
int pushButton2 = 12;
int pushButton3 = 10;
int pushButton4 = 8;
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// make the pushbutton's pin an input:
pinMode(pushButton1, INPUT);
pinMode(pushButton2, INPUT);
pinMode(pushButton3, INPUT);
pinMode(pushButton4, INPUT);
}
// the loop routine runs over and over again forever:
void loop() {
String char1;
int buttonState1 = digitalRead(pushButton1);
int buttonState2 = digitalRead(pushButton2);
int buttonState3 = digitalRead(pushButton3);
int buttonState4 = digitalRead(pushButton4);
if (buttonState1 == 1) Serial.print("A");
if (buttonState2 == 1) Serial.print("B");
if (buttonState3 == 1) Serial.print("C");
if (buttonState4 == 1) Serial.print("D");
delay(150);
}
Comments