Getting Started In A World of Robotics

Getting Started In A World of Robotics is a presentation which I have given on multiple occasions as a speaker for Project GEIT (Goans Empowered with Information Technology). Its purpose is to introduce students to the basics of hobby robotics and to inculcate a ‘how-stuff-works’ attitude towards new technology in as simple a manner as possible. Students can also learn how to build a simple robot of their own using the concepts shown in the presentation.

Getting started in a world of Robotics

Rexplorer v2

Rexplorer v2

Rexplorer v2 is a fully autonomous self-mapping robot to be used for indoor purposes.

My original intention was to develop a robot which could map an unknown area and relay the data to a monitoring system so as to provide real-time feedback about the layout of external environment.

I ended up making a robot that maps its own path, generally sticks to moving along the periphery of a room and sends a rough sketch of its traversed path to a smartphone via bluetooth.

This robot is part of the Rexplorer Project and is only an experimental prototype. There are certain conditions for sensing which have not yet been included, due to which undesirable movement may be caused. (Bug-fixes for the same will feature in the next version along with improved sensing algorithms and ultrasonic sensors.)

How it works:

There are 3 infrared proximity sensors at the front and sides of the robot which detect obstructions in its path. These digital signals are sent to an AVR micro-controller (ATMEGA 328 on Arduino UNO) which decides in which direction the robot should turn. The decision then activates the respective motors by sending a set of signals to the motor driver. Simultaneously, a second signal is sent to an Android application on a smartphone, via Bluetooth, containing information about the robot’s current movement which is in turn, used to draw a sketch of its path as it moves in real-time.

The Android application was made using MIT App Inventor 2 and the robot’s program was coded in the Arduino IDE (Integrated Development Environment), based on C++.

List of components: (all components are available at online stores such as robokits.co.in)

  • Wheels – 4 nos.
  • DC Geared motors – 4 nos.
  • Arduino UNO – 1 no. (Any version of Arduino can be used with the given code, provided it has the same or greater number of I/O pins and relevant changes are made in the uploading procedure. Additionally, any development board can be used provided the code’s logic remains the same and sufficient I/O pins are available.)
  • HC-05 bluetooth module – 1 no.
  • Infrared proximity sensors – 3 nos.
  • L298N motor driver – 1 no.
  • Lithium-ion rechargeable battery – 1 no.
  • Jumper wires – lots!

And finally, the codes! As always, please feel free to utilise, remix and improvise upon the codes. (And let me know how it went in the comments below!)

Smartphone application –

Arduino code –

int l1 = 6;
int l2 = 5;
int r1 = 11;
int r2 = 9;

int rs = 100;
int ls = 100;
int rts = 130;
int lts = 130;
//Coded by Raunak Hede-http://raunakhede.com
//drive system
#define f analogWrite(l1, ls); analogWrite(l2, 0); analogWrite(r1, rs); analogWrite(r2, 0);
#define b analogWrite(l1, 0); analogWrite(l2, ls); analogWrite(r1, 0); analogWrite(r2, rs);
#define l analogWrite(l1, 0); analogWrite(l2, lts); analogWrite(r1, rts); analogWrite(r2, 0);
#define r analogWrite(l1, lts); analogWrite(l2, 0); analogWrite(r1, 0); analogWrite(r2, rts);
#define s analogWrite(l1, 0); analogWrite(l2, 0); analogWrite(r1, 0); analogWrite(r2, 0);
#define d delay(200);

//individual hemisphere control
#define leftfor analogWrite(l1, lts); analogWrite(l2, 0);
#define rightfor analogWrite(r1, rts); analogWrite(r2, 0);

#define leftstop analogWrite(l1, 0); analogWrite(l2, 0);
#define rightstop analogWrite(r1, 0); analogWrite(r2, 0);

#define leftback analogWrite(l1, 0); analogWrite(l2, lts);
#define rightback analogWrite(r1, 0); analogWrite(r2, rts);

//MAPPING system
#define forward Serial.write("1");
#define backward Serial.write("4");
#define left Serial.write("3");
#define right Serial.write("2");
#define forright Serial.write("1");Serial.write("2");
#define backright Serial.write("1");Serial.write("2");
#define forleft Serial.write("4");Serial.write("3");
#define backleft Serial.write("4");Serial.write("3");
#define stp Serial.write("0");
int state;
int s1,s2,s3;
void setup()
{
pinMode(l1, OUTPUT);
pinMode(l2, OUTPUT);
pinMode(r1, OUTPUT);
pinMode(r2, OUTPUT);
pinMode(A0, INPUT);
pinMode(A2, INPUT);
pinMode(A3, INPUT);
Serial.begin(9600); //initialize serial communication at 9600 bits per second
pinMode(13,OUTPUT);digitalWrite(13,LOW);
}

void loop()
{
 if(Serial.available()>0)
 {
 int fse=digitalRead(A0);//front
 int lse=digitalRead(A2);//digital
 int rse=digitalRead(A3);//digital
//specify sensor limits
 int fsl=0;
 int lsl=0;
 int rsl=0;
//sets to 1 if closed and to 0 if open
 if(lse==lsl){s1=1;}else{s1=0;}
 if(fse==fsl){s2=1;}else{s2=0;}
 if(rse==rsl){s3=1;}else{s3=0;}

 if(s1==0 && s2==0 && s3==0)
 {//no blocks
 forward;
 f;delay(100);
 }
 else if(s1==1 && s2==0 && s3==1)
 {//sides blocked
 forward;
 f;delay(100);
 }
 else if(s1==1 && s2==1 && s3==1)
 {//all blocked- to rev- add about turn
 stp;
 s;
 }
 else if(s1==1 && s2==1 && s3==0)
 {//turn 90 right
 left;
 r;delay(400);
 }
 else if(s1==0 && s2==1 && s3==1)
 {//turn 90 left
 left;
 l;delay(400);
 }
 else if(s1==0 && s2==0 && s3==1)
 {//wall on right
 forward;
 rightfor;leftstop;
 }
 else if(s1==1 && s2==0 && s3==0)
 {//wall on left
 forward;
 leftfor;rightstop;
 }
 //T-junctions
 else if(s1==0 && s2==1 && s3==0)
 {// front block- turn 90 right
 right;
 r;delay(400);
 }
 }
 else{s;}
}
at school

Rexplorer v2 @ Sharada Mandir School Science Fair 2017

A speedy visit to Bangalore

A speedy visit to Bangalore

I returned from Bangalore a week back, after making a few long overdue visits.

To Inventrom:
After almost a year and a half, I met my mentor, Mr. Pranav Pai Vernekar (Founder-Inventrom) and had a chance to see the latest version of Inventrom’s flagship product: the Bolt 2 Internet Of Things platform.

I’ve had previous experience with other IOT platforms as well as Bolt v1, so here’s a short report highlighting its salient features:
Bolt is an IOT development platform with full cloud support, for enterprise-ready products and solutions.
The size and dimensions of the board allows easy storage and portability. It’s about half the size of its predecessor and almost a quarter the size of a Raspberry Pi Model B. Most of all, the speed of its processor is 300% faster!
The board itself has no external storage (external micro-SD card), but the codes can be pushed as files onto the cloud as ‘updates’.
Bolt 2 doesn’t have extra reference files within the system since everything is stored in the cloud, so it’s next to impossible to steal any data (Wi-Fi password, etc.) from the extra text files.
(This was the first security breach I found in the previous version of Bolt. Thankfully it’s been rectified.)
Bolt has 6 input/output (I/O) pins, of which there are 5 digital I/O’s and one analog pin.
It doesn’t have an AVR micro-controller (unlike its predecessor) and all the thinking is done by the ESP-8266 Wi-Fi module, thus saving space as well as energy.
The initial setup is highly intuitive and is over before you know it (just 4 steps).

Inventrom’s new office in Indiranagar, Bangalore is a swanky shared-workspace area. Coffee, beanbags and an excellent broadband connection are just a part of the deal which landed them here.

Note: Inventrom still has a branch office in Panaji, Goa, but their HQ is now in Bangalore.

To Mukunda Foods:
First off, I love dosas. I’m a Goan, but my breakfast culinary preferences are partial to South Indian cuisine.
During this visit, I had a chance to see the famous Dosamatic in action and also meet the awesome people behind it.

The one & only – DOSAMATIC!

Dosamatic is a dosa-lovers dream come true! It’s a table-top autonomous dosa production machine which can make an astonishing 50 dosas per hour at the touch of a button! The loading procedure is extremely simple and straightforward:(3 containers for oil, water & batter) just pour in the oil, water and batter (you get ready-made batter quite easily nowadays) in the respective containers and run the machine.

Mr. Rakesh Patil explains how the dosas are made

And do you get the same old plain, boring dosa every time? No! The Dosamatic can be configured as per the user’s fancy, which includes plain dosa, masala dosa as well as uthappams. If that wasn’t enough, these guys went ahead and added special adjustments for changing the thickness, size, fat content (for the diet-conscious), cooking time, roast temperature (which gives you variations in crispness), etc. Different varieties of batter can be used as per the owner’s preference.

What about pancakes and omelettes? They say that this too is possible.

As far as power consumption goes, the Dosamatic is quite energy efficient, consuming 3 Kilowatts per hour and running off a single phase 220/110V power supply.

Here’s the best part: The entire machine, right from the design, development and manufacture is done in-house at Mukunda Foods in Bangalore! Talk about ‘indi-genius’!

With the team (L-R): Ishwer Merwa, Rustam Ali, Rakesh Patil, Avishek Mishra, Waquar Mazhar

UPDATE : They recently launched another product called the Doughbot. Working on similar lines as Dosamatic, this machine can give you 150 ready-to-cook rotis/puris/parathas in an hour and run continuously for 14 hours making over 1200 dough balls! The input parameters can be changed for size, softness and quantity as well as the type of flour being used, which includes maida, atta, bajra, ragi and millet. The machine itself weighs only 20 kg, is 1×0.5 feet in size and consumes just half a kilowatt of power.

To Bizmobile IT Solutions:

Last but not the least, a quick visit to the office of Bizmobile IT Solutions (a mobile and cloud platform with ready to use last mile apps) to meet the CEO, Mr. Rakesh Tergundi.

Had an excellent opportunity to learn more about their flagship product: Mobijini

Mobijini is a single cross-platform mobile application which can be used by anyone and everyone in a business supply chain. It handles everything from the order collection, shipment tracking, payment collection, stock updates, etc. and ensures that everyone is kept up to date with the latest status of the order.

In addition to this, it can also be integrated with pre-existing order management systems and e-commerce portals. The app has been utilised in various sectors ranging from pharmaceuticals to real estate and logistics to micro-finance.

And back home…

Over three days, I visited three fantastic companies and learn’t not only about their products but also the workings of the companies themselves! Something I never really paid attention to until very recently.

Special thanks to:

Pranav Pai Vernekar (Founder – Inventrom)

Rakesh Patil (R&D Head – Mukunda Foods Pvt. Ltd.)

Rakesh Tergundi (Founder – Mobijini)

Compliments of the season & Happy New Year!

Compliments of the season & Happy New Year!

”Tis the season!’, or rather, ”Twas the season!’

I recently started tinkering around with a servo motor (my Christmas present) and decided to put it to use on our tree.

As you might have figured out, it’s a smartphone-tilt-sensitive star, sitting atop the tree on a servo motor.

When the phone is tilted to the right, the star turns left and vice-versa.

The signals from the phone’s internal accelerometer (only x-axis is used here) are sent via bluetooth to the HC05 bluetooth module, which in turn, sends it to the Arduino UNO. The Arduino then converts the raw data into PWM (pulse width modulation) signals and transmits it through digital pin 9 to the servo motor.

The project makes use of the following hardware:

  • Arduino UNO
  • HC05 (bluetooth module)
  • Plastic geared servo motor

And software:

  • Android app made using MIT App Inventor 2
    • Components used:

    • A few other settings to be changed:
      • BluetoothClient1 – Leave ‘Secure’ checkbox unchecked
      • Clock1 – set ‘TimerInterval’ value to 1
      • AccelerometerSensor1 – set ‘MinimumInterval’ value to 1000 and set ‘Sensitivity’ option to weak.
    • Code:
  • Arduino code:

#include <Servo.h>

Servo myservo;
void setup()
{
Serial.begin(9600);
myservo.attach(9);
delay(1000);
}void loop()
{
int val=0;
int state=Serial.parseInt();
val = map(state,-22,0,0,180);
myservo.write(val);
Serial.println(val);
}

The pin connections are fairly straightforward:

Servo motor red – Arduino 5v
Servo motor black/brown – Arduino GND
Servo motor yellow/white (PWM input) – Arduino Digital Pin 9 (PWM)
HC05 VCC – Arduino 3.3v
HC05 GND – Arduino GND
HC05 Tx – Arduino Rx
HC05 Rx – Arduino Tx

Have a great year ahead!

Rexplorer v1 – A robot programmed in Scratch GPIO

Rexplorer v1 – A robot programmed in Scratch GPIO

For the first time, I’ve built a fully functional robot with my trusty Raspberry Pi 2. My last attempt at connecting a motor driver to a Pi resulted in a burnt pi; but that was because I connected its 5v output to the driver’s 5v output pin (recipe for disaster).

Rexplorer is the successful result of research preceded by a burnt Raspberry Pi Mod B and an L298N motor driver which blew a fuse.

By the end of this tutorial you will have a fully functional obstacle detecting robot (provided you follow the instructions carefully).

Disclaimer: The author of this tutorial will not be held responsible for any burnt Raspberry Pi(e)s or indirect damage caused to the same due to negligence (as was the case with the author’s).

As you may already know, the Raspberry Pi is a Linux OS computer.

So first, lets take a quick look at the bot (when unplugged from the monitor/screen, keyboard, mouse and any other peripherals).

HARDWARE

  • Raspberry Pi – Model B 2 or any 40-pin Pi; you can also use Model B, A+, B+ or Zero if you know their respective pinouts
  • Raspberry Pie – Optional, unless you’re hungry
  • Motor Driver – Preferably based on L298N
  • BO motors – 2 nos.
  • Wheels for BO motors – 2 nos.
  • Castor wheel  – 1 BIG wheel
  • Mechanix/Mechano built chassis – You can use any chassis for provided there is space for motors and sensors
  • Jumper wires – As many as you can find
  • A power bank – Only to power the Raspberry Pi and can be substituted with any decent 5v power supply
  • Lithium ion 12v battery pack – To power up the motors.
  • Toggle switch – Optional, as it will be used for the power supply to the motor driver

The mouse, keyboard, monitor/screen and other peripherals which are connected to the Pi when it is not running headless (without a display), will now be referred to as the ‘station’.

The HDMI cable connecting the Pi’s display output should be at least one metre long.

The software of PiBot is done in a modified  version of the programming language (interface actually) called Scratch. The modified version which we will be using is called Scratch GPIO (version 7).

Scratch GPIO is modelled on Scratch v1.4, but in addition to all the other features, it also gives a user direct access to all of the Pi’s GPIO pins. This makes it easy to program the Pi as a robot with motors, sensors and various other hardware peripherals.

Connect all the hardware as shown in the schematic…

pibot_schematic

Or as explained here in words…

The motor driver’s 2 enable and 4 input pins are connected to pins 31, 32, 35, 36, 37, 38 of the Pi respectively; the motors are directly connected to the driver’s output terminals; the driver’s power supply is connected to the 12v battery (directly or with a toggle switch in between) and the GND/negative wires is also connected to the Pi’s GND (pin 40); the proximity sensor’s VCC is connected to the 3.3v output at pin 1 of the Pi, GND at pin 6, and O/P (output) at pin 7.

Between the two, I think you’ll prefer the schematic 😜

SOFTWARE

Boot the Pi to install Scratch GPIO with an internet connection.

Open the LXterminal and type:

wget http://bit.ly/1wxrqdp -O isgh7.sh

After the installer has been downloaded, type:

sudo bash isgh7.sh

Now that Scratch GPIO 7 and its accessory files are installed, let’s get coding!

Open Scratch GPIO7 (you’ll see a shortcut on the desktop) and drag the following blocks into the blank grey area:

pibot_code2

pibot_code3

The ‘broadcast’ blocks normally send messages which act as signals in the programme, but in this case they’re actually changing the state of the GPIO pins. The syntax for any output through broadcast is as follows:

pin<pin number><state>

Where ‘pin number’ is the GPIO pin number as per the pinout numbering and ‘state’ is the output at that pin i.e. either high or low.

Test it by clicking on the arrow keys on your Pi’s keyboard and make sure that the pin numbers are correct.

Right now, the robot should move forward, backward, turn left or right depending on the arrow key pressed. This is a quick and easy way to test your motor driver connections and make sure the wires connect the right pins.

To make it ‘smart’ we need to throw in another script for, let’s say, obstacle detection.

Open the background’s script area by double clicking on its icon near the list of sprites.

Now drag these blocks into the grey area:

pibot_code1

Save the project and close ScratchGPIO7.

Lastly, open an LXterminal window and type:

sudo raspi-config

A configuration list should open. Choose option 3 i.e. Enable boot to Desktop/Scratch and at the next list, choose Desktop log in as user ‘pi’ at the Graphical Desktop.

Now reboot your Raspberry Pi and watch the magic unfold!

As soon as the desktop loads, open ScratchGPIO7, open your project (if it isn’t already open) and hit ‘Enter’. The green flag script(s) should start automatically. The motors will now be activated so please check if the Pi is connected and accordingly hold on to it to prevent any untoward incidents.

The Pi can also be accessed wirelessly over SSH (Secure Shell) and VNC (Virtual Network Computing), so you could consider installing RealVNC on the Pi and a laptop/PC to control it (the robot) remotely.

The robot should (as every good obstacle detector does) stop when it detects an obstacle and continue moving otherwise.

KUKA Robotics Training Programme

KUKA Robotics Training Programme

Last week, I attended a training programme at KUKA Robotics Pune from the 2nd to 4th of May.

During the programme I learn’t how to jog and master the axes, calibrate the various co-ordinate systems and tools, calibrate it for different payloads and supplementary loads and also some basic logic programming.

The trip to KUKA was a bit long as the first day of the training programme coincided with the day of our return from a very long vacation. We took a flight from Amsterdam to Dubai, Dubai to Bombay and Bombay to Goa (with stop-overs) and reached home at 10:30 in the night. The very same night (at around 1:00 a.m.) we left for Pune by road. On reaching Pune at 9:30 the next morning, we drove to the KUKA Robotics Training Centre where the session had already begun. I was an hour late (and jet lagged) but soon caught up with what was being done. There were also three other gentlemen in the training programme who were from CSIR-National Aerospace Laboratories, Bangalore.

Day 1:

Introduction to jogging the 6 axes of a KR16-2 KUKA robotic arm. The robotic arm is controlled using keys or a type of joystick from a handheld device called a smartPAD while jogging. There are 4 operating modes of the robot, namely T1, T2, Auto and Auto-External. Of these 4 modes, T1 allows enabling of motion from the smartPAD with a velocity limit of 25 cm/s. T2 does not have a velocity restriction, (so the safety door of the work area must be kept closed and nobody should be present inside) but programmes running in this mode also require motion to be enabled from the smartPAD. Auto mode allows the program to run without human intervention. Auto-External requires an external PLC to be connected, usually because inputs may be required from the operator in that particular program, but otherwise runs autonomously. I experimented with a gripper attachment on the robotic arm and learn’t how to master each of the robot’s axes with an EMD (Electronic Mastering Device).

Day 2:

Calibration of the robot for carrying a payload, supplementary load and tool. I learnt to calibrate the Tool and Base Co-ordinate Systems and also some basic programming for Point-to-point motion (PTP/Axis specific movement), Linear & Circular motion (Controlled Path movement). In addition to these, I also learn’t to archive and restore files in the smartPAD.

Day 3:

Usage of continuous motion and SPLINE movement and change of orientation for the same position (x,y,z) in PTP motion. Collision detection through changes in torque and synchronised output motions were also covered along with logic programming. There are 5 basic concepts in logic programming: inputs, outputs, timers, time dependant ‘wait’ functions and signal dependant ‘wait’ functions. Outputs can further be subdivided into simple outputs, pulse outputs and motion synchronised outputs.

These 3 days have been an invaluable learning experience.

Sincere thanks to Mr. Saurabh Gupte, Mr. Ravi Teja and KUKA Robotics for permitting me to attend the training programme.

KUKA training programme_group photo

Visit to the German Space Operations Centre

Visit to the German Space Operations Centre

During the first month of my summer vacation I had an opportunity to visit the DLR – Deutches Zentrum für Luft und Raumfahrt (i.e. German Aerospace Centre) at Oberpfaffenhofen near Munich in Germany. The DLR is a branch of the European Space Agency (ESA).

But before I proceed any further, a little background on how this happened.
Our first stop in Germany was Munich. The host of the place where we stayed, works at the DLR. On hearing of my interest in space and technology, he offered to show us around the department he works in (which I most enthusiastically accepted!).
And so the next day, we visited the German Space Operations Centre (GSOC) of the DLR. It is here, where communication takes place with the astronauts on board the International Space Station (ISS). GSOC has played a key role in operating a multitude of manned and unmanned spacecraft missions for the past 35 years. Currently, they are preparing for operations on the European satellite navigation system: Galileo, a constellation of 30 satellites which will be in control of the DLR for at least 20 more years.
We were also shown a scale mock-up of Europe’s module on the ISS, the construction of which, our gracious host was involved in. In the same area, was a pilot simulator mounted on a massive KUKA robotic arm.
IMG_20160508_123919IMG_20160508_124027
The highlight of our visit: a once-in-a-lifetime opportunity to see the redundant control room of GSOC. In other words, all the activity that happen in the main control room also takes place on the computers and real-time monitoring systems in the redundant room. In the eventuality that something goes wrong in the main control room, the personnel would still be able to continue operations from the redundant room. And this is where I learn’t the rule of redundancy: Everything should be redundant.
In the redundant room of GSOC, I saw the astronauts’ work time-table, current location and signal transmission status of the ISS, various communication and earth monitoring satellites’ locations, heard live communication between other control centres all over the world (like the one at NASA!) and even sat in the redundant chair of the COL FLIGHT! (Flight Director)
IMG_20160508_123640
The visit to GSOC was the best part of my vacation and I will remember it forever.
There were two major things that I learn’t on this visit:
The first, as I’ve mentioned earlier, the importance of redundancy.
The second: Pass it on. Pass on the knowledge and experience that you have, to those who share an interest in it. Help a spark of interest become a flame of knowledge. The knowledge that I have gained on this visit will be invaluable to me because it was through an experience. Fernando saw my interest and decided to pass on a part of his experience to me.
As Louis L’amor once said “Knowledge is like money: to be of value it must circulate, and in circulating it can increase in quantity and, hopefully, in value.”
Thanks for making this possible Fernando!
Quark 2016 – BITS Pilani, K.K. Birla Goa Campus

Quark 2016 – BITS Pilani, K.K. Birla Goa Campus

Quark 2016 – A Cosmic Odyssey

Days of festival: 5th, 6th & 7th February 2016

I participated in Line Following, Roborace and, for the first time, Open Showcase!

RoboRace

Objective: Design & build a remote controlled all-terrain racer that can traverse any given path with obstacles like rocks, sand, slopes, uneven ground, mud, etc.

Dates of competition: 5th & 6th

Venue: Uneven grounds outside B-Dome

Home test report: Excellent traction, thanks to the custom-made wheels (each wheel was actually a pulley with a track belt bound tightly over it) Gains speed very quickly and can even climb out of a small car tyre.

Results:

5th Feb, Round 1 – The bot completed the track without stopping, and clocked a very good timing, however, the high traction wheels turned out to be a massive hindrance while making spot turns. This factor slowed it down, but it made up for that on the straight paths.

The bot qualified for Round 2, which was to be held on Day 2, but unfortunately, due to a last minute shorting onboard the wireless module, the bot was unable to participate.

Quark_2016_RoboRace_participation_certificate

Open Showcase

Objective: Present an innovative idea that solves a problem.

Dates of competition: Day 2

Venue: CC lobby

My Idea (for the EEE category): CUA (Computer Usage Alert) is a plug-n-play USB device that alerts you to get up and stretch at 20 minute intervals. It has an ATtiny85 micro controller with a program that sends a signal to a buzzer to beep every 20 minutes, thereby alerting you to get up. This process continues until it is unplugged or the computer/laptop to which it is plugged is shut down.

The judging criteria was as follows:

  • Innovation
  • Feasibility and Sustainability
  • Cost Effectiveness
  • Social Viability
  • Discipline
  • Project Report

Quark_2016_Open_Showcase_participation_certificate

Line Following

Objective: Design, build & program a line following robot (LFR) which can traverse a black track on a white background with obstacles like acute angle, obtuse angles, right angles, dashed lines, curves and reach the finish line in shortest possible time. The track width will be 2cm to 3cm. (As per the rules mentioned online)

Screen Shot 2016-02-16 at 8.28.51 pm

Dates of competition: 6th & 7th

Venue: C-306

Home test report: Running very well. I’d say that is has an 80% chance of making a new record.

Competition day: “Holy mackerel! The track width is 4cm!“. I asked the organiser about it. He measured the track width and calmly told me that extra calibration time would be given. And as if to put salt on that wound, the track had 4 places where there were curved, dashed lines with acute turns onto more curved lines!

Results:

6th Feb, Trial 1 – The LFR started out well and then went completely cuckoo. Though it has a PID algorithm in it, the LFR seems to be in its own world. (Thanks to the extra centimetre in the width)

6th Feb, Trial 2 – I managed to fix a few turns, but the PID algorithm still seems to be completely inactive.

(Fortunately, everyone had problems running on the first day, so everyone qualified for the next round on day 2. That night, I sat coding till 1:00 A.M. and finally managed to fix it.)

7th Feb, Trial 1 – The new code is working and the PID is perfect, but a few changes still need to be made in the acute turns. Overall, it’s running well.

7th Feb, Trial 2 – This run went very well, except for the fact that it went off the track 5 times (which means that 25 seconds will be added to my total time of 38 seconds, as a penalty)

I finished my turn just after lunchtime, so I had the rest of the day to go around the campus and watch the final rounds of the other competitions.

At around 4 o’clock I received a phone call from the organiser, telling me that I had won the 2nd place.

IMG_20160207_185732

 

For all you geeks out there, here’s my LFR code. Feel free to tweak and reuse:

#include <QTRSensors.h>
//Code written by Raunak Hede
//https://raunakhede.com
#define Kp 1 // experiment to determine this, start by something small that just makes your bot follow the line at a slow speed
#define Kd 15 // experiment to determine this, slowly increase the speeds and adjust this value. ( Note: Kp < Kd) 
#define rightMaxSpeed 180 // max speed of the robot
#define leftMaxSpeed 180 // max speed of the robot
#define rightBaseSpeed 50 // this is the speed at which the motors should spin when the robot is perfectly on the line
#define leftBaseSpeed 50  // this is the speed at which the motors should spin when the robot is perfectly on the line
#define NUM_SENSORS  8     // number of sensors used
#define TIMEOUT      2500  // waits for 2500 us for sensor outputs to go low
#define EMITTER_PIN  12     // emitter is controlled by digital pin 2

#define rightMotor1 4
#define rightMotor2 11
#define rightMotorPWM 5
#define leftMotor1 3
#define leftMotor2 6
#define leftMotorPWM 10

int P, D;
int leftMotorSpeed = 50;
int rightMotorSpeed = 50;
int turn = 100;

QTRSensorsRC qtrrc((unsigned char[]) {14, 15, 16, 17, 18, 19, 7, 8}, NUM_SENSORS, TIMEOUT, EMITTER_PIN);//sensor connected
unsigned int sensorValues[NUM_SENSORS];
void setup()
{
  pinMode(rightMotor1, OUTPUT);
  pinMode(rightMotor2, OUTPUT);
  pinMode(rightMotorPWM, OUTPUT);
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotor2, OUTPUT);
  pinMode(leftMotorPWM, OUTPUT);
  
  #define rup digitalWrite(rightMotor1, HIGH);digitalWrite(rightMotor2, LOW);
  #define lup digitalWrite(leftMotor1, HIGH);digitalWrite(leftMotor2, LOW);
  #define rdown digitalWrite(rightMotor1, LOW);digitalWrite(rightMotor2, HIGH);
  #define ldown digitalWrite(leftMotor1, LOW);digitalWrite(leftMotor2, HIGH);
  
  #define f lup;analogWrite(leftMotorPWM, 80); rup;analogWrite(rightMotorPWM, 80);
  #define l ldown;analogWrite(leftMotorPWM, turn);  rup;analogWrite(rightMotorPWM, turn);
  #define r lup;analogWrite(leftMotorPWM, turn);  rdown;analogWrite(rightMotorPWM, turn+50);
  #define b ldown;analogWrite(leftMotorPWM, 80); rdown;analogWrite(rightMotorPWM, 80);
  #define s analogWrite(leftMotorPWM, 0);  analogWrite(rightMotorPWM, 0);

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  pinMode(12, OUTPUT);
  digitalWrite(12, HIGH);
  for (int i = 0; i < 500; i++)  // make the calibration take about 10 seconds
  {
    qtrrc.calibrate();       // reads all sensors 10 times at 2500 us per read (i.e. ~25 ms per call)
  }
  digitalWrite(13, LOW);// turn off Arduino's LED to indicate we are through with calibration
 
  //print the calibration minimum values measured when emitters were on
  Serial.begin(9600);
  for (int i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtrrc.calibratedMinimumOn[i]);
    Serial.print(' ');
  }
  Serial.println();
  
  // print the calibration maximum values measured when emitters were on
  for (int i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtrrc.calibratedMaximumOn[i]);
    Serial.print(' ');
  }
  Serial.println();
  Serial.println();
  delay(500);
}
int lastError = 0;

void loop()
{
  unsigned int position = qtrrc.readLine(sensorValues);
  if (sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] > 900 && sensorValues[4] > 900 && sensorValues[3] > 900 && sensorValues[2] > 900 && sensorValues[1] > 900 && sensorValues[0] > 900)
  {//right
      s;delay(50);  r;delay(300); s;delay(50);
  }
  else if (sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] > 900 && sensorValues[4] > 900 && sensorValues[3] > 900 && sensorValues[2] > 900 && sensorValues[1] < 900 && sensorValues[0] < 900)
  {//left
      s;delay(50);  l;delay(300); s;delay(50);
  }
  
  else if (sensorValues[7] < 900 && sensorValues[6] > 900 && sensorValues[5] > 900 && sensorValues[4] > 900 && sensorValues[3] > 900 && sensorValues[2] > 900 && sensorValues[1] > 900 && sensorValues[0] > 900)
  {//right
      s;delay(50);  r;delay(280); s;delay(50);
  }
  else if (sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] > 900 && sensorValues[4] > 900 && sensorValues[3] > 900 && sensorValues[2] > 900 && sensorValues[1] > 900 && sensorValues[0] < 900)
  {//left
      s;delay(50);  l;delay(280); s;delay(50);
  }
  
  else if (sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] < 900 && sensorValues[0] < 900)
  {//acute right
    f;
  }
  
  else
  {//Execute the PID algorithm
    unsigned int sensors[8];
    int position = qtrrc.readLine(sensors);//get calibrated readings along with the line position
    int error = position-3500;
    
    P = Kp * error;
    D = Kd * (error - lastError);
    
    int motorSpeed = P + D;
    lastError = error;
    
    int rightMotorSpeed = rightBaseSpeed + motorSpeed;
    int leftMotorSpeed = leftBaseSpeed - motorSpeed;
  
    if (rightMotorSpeed > rightMaxSpeed ) rightMotorSpeed = rightMaxSpeed; // prevent the motor from going beyond max speed
    if (leftMotorSpeed > leftMaxSpeed ) leftMotorSpeed = leftMaxSpeed; // prevent the motor from going beyond max speed
    if (rightMotorSpeed < 0) rightMotorSpeed = 0; // keep the motor speed positive
    if (leftMotorSpeed < 0) leftMotorSpeed = 0; // keep the motor speed positive
  
    //move forward with appropriate speeds
    digitalWrite(rightMotor1, HIGH);
    digitalWrite(rightMotor2, LOW);
    analogWrite(rightMotorPWM, rightMotorSpeed);
    digitalWrite(leftMotor1, HIGH);
    digitalWrite(leftMotor2, LOW);
    analogWrite(leftMotorPWM, leftMotorSpeed);
  }
}
Techfest 2015 – IIT Bombay

Techfest 2015 – IIT Bombay

Techfest 2015!

IIT Bombay’s most awaited techfest was held last month from 26th to 28th December.

I participated in Maze Runner, a competition which was part of an event called Technovoltz.

The participants had to build an autonomous robot which could follow a white line and keep track of directions while traversing the maze. The bot had to analyse the path in the dry run. In the final run, it then had to take the correct path through the maze in minimum possible time.

The maze!

Main components of the robot:

After a lot of preparation, I entered the double doors of the Girish Gaitonde Lecture Hall Complex

At the entrance to the lecture hall complex, I was assigned the first slot.

Inside lecture room 002 (for that was the venue), it was completely dark. The maze was made from white vinyl strips pasted on a large wooden board, which was painted black.

The maze also had certain checkpoints, each of which when crossed, added 25 points to the total score.

At the end of the track was a white thermocol block (polystyrene) which on sensing, the maze solver had to blink a red LED to get 5 points.

When my turn came, I calibrated my robot’s sensors (in the fashion that all Pololu sensors are calibrated), set it into Mode 1 (maze analysis mode) and placed it at the start point.

(Note: Mode 2 is for the final run, in which the robot processes the path recorded in the dry run, eliminates all the bad turns and traverses the shortest path from start to end.)

Each participant is given three chances to restart.

The first time, it took an about turn right at the beginning and veered off the track. (Recalibration…)

The second time it went 2 inches forward before going completely cuckoo. (Recalibration again…)

The third time, thankfully, it went ahead and started the run.

All went well on the first run. Yippee!

The only problem was that it took a double turn at a dead-end. This mean’t that I would have to leave it in mode 1 again for the second run. If I put it in mode 2 now, it would get confused while processing the double turn and refuse to move.

So leaving it in mode 1, I took it back to the start point for the final run.

And right there, I made the mistake of turning it off and on again.

When a robot is turned off and on, the sensor calibration has to be done ALL OVER AGAIN.

I re-calibrated it, but something must have gone wonky because it got stuck in a loop and refused to proceed.

In the end, I scored enough points for a participation certificate. (Minimum points required: 60)

A very important point to note is that during the final testing at home (on a regular flex sheet) the maze solver solved the maze five out of five times.

IMG_20151226_073946124

This was quite an achievement and a great learning experience.

Lessons learn’t:

  • The material of the track adversely affects the functioning of a maze solver’s sensors and caster wheel.
  • Ensure that variables for turning are appropriate for any texture and that motors & wheels are also powerful enough.

 

For all you geeks out there who are into programming, here’s the code. Feel free to remix and use.

#include <QTRSensors.h>
// Code written by Raunak Hede  – www.raunakhede.com
#define Kp 1 // experiment to determine this, start by something small that just makes your bot follow the line at a slow speed
#define Kd 15 // experiment to determine this, slowly increase the speeds and adjust this value. ( Note: Kp < Kd)
#define rightMaxSpeed 250 // max speed of the robot
#define leftMaxSpeed 250 // max speed of the robot
#define rightBaseSpeed 100 // this is the speed at which the motors should spin when the robot is perfectly on the line
#define leftBaseSpeed 100 // this is the speed at which the motors should spin when the robot is perfectly on the line
#define NUM_SENSORS 8 // number of sensors used
#define TIMEOUT 2500 // waits for 2500 us for sensor outputs to go low
#define EMITTER_PIN 12 // emitter is controlled by digital pin 2
#define rightMotor1 4
#define rightMotor2 11
#define rightMotorPWM 5
#define leftMotor1 3
#define leftMotor2 6
#define leftMotorPWM 10
#define switchpwr 2 //mode input taken from D9
int leftMotorSpeed = 50;// do not change back to/exceed 100
int rightMotorSpeed = 50;
int turn = 100;
QTRSensorsRC qtrrc((unsigned char[]) {14, 15, 16, 17, 18, 19, 7, 8}, NUM_SENSORS, TIMEOUT, EMITTER_PIN);//sensor connected
unsigned int sensorValues[NUM_SENSORS];
void setup()
{
pinMode(9, INPUT_PULLUP);
pinMode(switchpwr, OUTPUT);
pinMode(rightMotor1, OUTPUT);
pinMode(rightMotor2, OUTPUT);
pinMode(rightMotorPWM, OUTPUT);
pinMode(leftMotor1, OUTPUT);
pinMode(leftMotor2, OUTPUT);
pinMode(leftMotorPWM, OUTPUT);
#define rup digitalWrite(rightMotor1, HIGH);digitalWrite(rightMotor2, LOW);
#define lup digitalWrite(leftMotor1, HIGH);digitalWrite(leftMotor2, LOW);
#define rdown digitalWrite(rightMotor1, LOW);digitalWrite(rightMotor2, HIGH);
#define ldown digitalWrite(leftMotor1, LOW);digitalWrite(leftMotor2, HIGH);
#define f lup;analogWrite(leftMotorPWM, leftMotorSpeed); rup;analogWrite(rightMotorPWM, rightMotorSpeed);
#define l ldown;analogWrite(leftMotorPWM, turn); rup;analogWrite(rightMotorPWM, turn);
#define r lup;analogWrite(leftMotorPWM, turn); rdown;analogWrite(rightMotorPWM, turn);
#define b ldown;analogWrite(leftMotorPWM, 80); rdown;analogWrite(rightMotorPWM, 80);
#define s analogWrite(leftMotorPWM, 0); analogWrite(rightMotorPWM, 0);
#define turnleft s;delay(50); l;delay(240); s;delay(300);
#define turnright s;delay(50); r;delay(290); s;delay(300);
#define hardturnleft s;delay(50); l;delay(1000); s;delay(300);
#define hardturnright s;delay(50); r;delay(1000); s;delay(300);
#define turnaround s;delay(50); l;delay(500); s;delay(300);
#define skip f;delay(200);
#define back b;delay(30);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
pinMode(12, OUTPUT);
digitalWrite(12, HIGH);
for (int i = 0; i < 200; i++) // make the calibration take about 10 seconds
{
qtrrc.calibrate(); // reads all sensors 10 times at 2500 us per read (i.e. ~25 ms per call)
}
digitalWrite(13, LOW);// turn off Arduino’s LED to indicate we are through with calibration
//print the calibration minimum values measured when emitters were on
Serial.begin(9600);
for (int i = 0; i < NUM_SENSORS; i++)
{
Serial.print(qtrrc.calibratedMinimumOn[i]);
Serial.print(‘ ‘);
}
Serial.println();
// print the calibration maximum values measured when emitters were on
for (int i = 0; i < NUM_SENSORS; i++)
{
Serial.print(qtrrc.calibratedMaximumOn[i]);
Serial.print(‘ ‘);
}
Serial.println();
Serial.println();
delay(500);
}
int lastError = 0;
char dir;
char directions[20];
char newdirections[20];
int i=-1;
void loop()
{
digitalWrite(switchpwr, HIGH);
int mode = digitalRead(9);
if (mode != 0)
{
unsigned int position = qtrrc.readLine(sensorValues);
if ((sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] < 900 && sensorValues[0] < 900) || (sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] > 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] < 900 && sensorValues[0] < 900))
{//right
s;delay(100);
unsigned int position = qtrrc.readLine(sensorValues);//Check again
if (sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] > 900 && sensorValues[4] > 900 && sensorValues[3] > 900 && sensorValues[2] > 900 && sensorValues[1] > 900 && sensorValues[0] > 900)//dead-end
{
dir = ‘R’;
back;
turnright;
i++;
directions[i] = dir;
}
else
{
dir = ‘F’;
skip;
i++;
directions[i] = dir;
}
}
else if ((sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] > 900 && sensorValues[0] > 900) || (sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] > 900 && sensorValues[1] > 900 && sensorValues[0] > 900))
{//left
dir = ‘L’;
turnleft;
i++;
directions[i] = dir;
}
else if (sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] < 900 && sensorValues[0] < 900)//junction
{
dir = ‘L’;
turnleft;
i++;
directions[i] = dir;
}
else if (sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] > 900 && sensorValues[4] > 900 && sensorValues[3] > 900 && sensorValues[2] > 900 && sensorValues[1] > 900 && sensorValues[0] > 900)//dead-end
{
dir = ‘B’;
turnaround;
i++;
directions[i] = dir;
}
else
{
unsigned int sensors[8];
int position = qtrrc.readLine(sensors);//get calibrated readings along with the line position
int error = 3500-position;
int motorSpeed = Kp * error + Kd * (error – lastError);
lastError = error;
int rightMotorSpeed = rightBaseSpeed + motorSpeed;
int leftMotorSpeed = leftBaseSpeed – motorSpeed;
if (rightMotorSpeed > rightMaxSpeed ) rightMotorSpeed = rightMaxSpeed; // prevent the motor from going beyond max speed
if (leftMotorSpeed > leftMaxSpeed ) leftMotorSpeed = leftMaxSpeed; // prevent the motor from going beyond max speed
if (rightMotorSpeed < 0) rightMotorSpeed = 0; // keep the motor speed positive
if (leftMotorSpeed < 0) leftMotorSpeed = 0; // keep the motor speed positive
//move forward with appropriate speeds
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
analogWrite(rightMotorPWM, rightMotorSpeed);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
analogWrite(leftMotorPWM, leftMotorSpeed);
}
}
else if (mode == 0)
{
s;
recheck:
for(int x=0; x<=sizeof(directions); x++)
{
if (directions[x] == ‘B’)//if there are B signals, go ahead with reprocessing.
{
if (directions[x-1]==’R’ && directions[x+1]==’R’)
{
directions[x-1]=0;
directions[x]=’F’;
directions[x+1]=0;
}
else if (directions[x-1]==’L’ && directions[x+1]==’L’)
{
directions[x-1]=0;
directions[x]=’F’;
directions[x+1]=0;
}
else if (directions[x-1]==’F’ && directions[x+1]==’F’)
{
directions[x-1]=0;
directions[x]=’B’;
directions[x+1]=0;
}
else if (directions[x-1]==’F’ && directions[x+1]==’L’)
{
directions[x-1]=0;
directions[x]=’R’;
directions[x+1]=0;
}
else if (directions[x-1]==’R’ && directions[x+1]==’L’)
{
directions[x-1]=0;
directions[x]=’B’;
directions[x+1]=0;
}
else if (directions[x-1]==’L’ && directions[x+1]==’F’)
{
directions[x-1]=0;
directions[x]=’R’;
directions[x+1]=0;
}
else if (directions[x-1]==’L’ && directions[x+1]==’R’)
{
directions[x-1]=0;
directions[x]=’B’;
directions[x+1]=0;
}
}
}
Serial.println();
//put the processed data into the same array (with no null characters)
int d = -1;
for (int a=0; a<=sizeof(directions); a++)
{
if (directions[a] != ‘\0’)
{
d++;
directions[d] = directions[a];
}
}
Serial.println();//check for any leftover B signals
for (int z=0; z<=sizeof(directions); z++)
{
if (directions[z] == ‘B’)
{
goto recheck;
}
}
for (int z=0; z<=sizeof(directions); z++)//Now print the final data from the new array
{
Serial.print(directions[z]);
}
Serial.end();
// Start final run with processed data
s; delay(6000);
int n = 0;
while(1)
{Serial.println(“Starting final run”);
unsigned int position = qtrrc.readLine(sensorValues);
if ((sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] < 900 && sensorValues[0] < 900) || (sensorValues[7] > 900 && sensorValues[6] > 900 && sensorValues[5] > 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] < 900 && sensorValues[0] < 900))
{
if (directions[n] == ‘R’)
{
turnright;
n++;
}
else if (directions[n] == ‘F’)
{
skip;
n++;
}
}
else if ((sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] > 900 && sensorValues[0] > 900) || (sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] > 900 && sensorValues[1] > 900 && sensorValues[0] > 900))
{
if (directions[n] == ‘L’)
{
turnleft;
n++;
}
else if (directions[n] == ‘F’)
{
skip;
n++;
}
}
else if (sensorValues[7] < 900 && sensorValues[6] < 900 && sensorValues[5] < 900 && sensorValues[4] < 900 && sensorValues[3] < 900 && sensorValues[2] < 900 && sensorValues[1] < 900 && sensorValues[0] < 900)//junction
{
if (directions[n] == ‘L’)
{
turnleft;
n++;
}
else if (directions[n] == ‘F’)
{
skip;
n++;
}
else if (directions[n] == ‘R’)
{
turnright;
n++;
}
}
else
{
unsigned int sensors[8];
int position = qtrrc.readLine(sensors);//get calibrated readings along with the line position
int error = 3500-position;
int motorSpeed = Kp * error + Kd * (error – lastError);
lastError = error;
int rightMotorSpeed = rightBaseSpeed + motorSpeed;
int leftMotorSpeed = leftBaseSpeed – motorSpeed;
if (rightMotorSpeed > rightMaxSpeed ) rightMotorSpeed = rightMaxSpeed; // prevent the motor from going beyond max speed
if (leftMotorSpeed > leftMaxSpeed ) leftMotorSpeed = leftMaxSpeed; // prevent the motor from going beyond max speed
if (rightMotorSpeed < 0) rightMotorSpeed = 0; // keep the motor speed positive
if (leftMotorSpeed < 0) leftMotorSpeed = 0; // keep the motor speed positive
//move forward with appropriate speeds
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
analogWrite(rightMotorPWM, rightMotorSpeed);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
analogWrite(leftMotorPWM, leftMotorSpeed);
}
}
}
}
Project GEIT

Project GEIT

During the last week of my Diwali vacations, I had the wonderful opportunity to be part of Project GEIT (Goans Empowered with Information Technology) and teach Scratch programming as a volunteer instructor to students at 3 village schools.

The project was divided into 10-day camps conducted at the following schools:

The aim of Project GEIT is to inculcate knowledge of computer programming and logical reasoning in village school students at an early age.

A huge advantage of using Scratch over many other development environments is:

  1. It has a very well-designed Graphical User Interface which makes it easy for even complete beginners to learn programming on their own.
  2. All the required components (if, else, print, delay, etc.) are present in the form of colour-coded blocks with specified shapes depending on what type of block it is (e.g. Input blocks are light blue, function blocks are yellow, animation blocks are deep blue, etc.) The blocks are also labelled in simple language which makes programming very simple. All the person has to do is drag & drop the blocks in the right places to make their program.
  3. And best of all, it works offline! At such schools, where there is no internet/broadband connection, Scratch was a blessing!

Ms. Sangeeta Naik (Project Lead) and Mr. Vincent Toscano (Backup Lead and Chorao School anchor) introduced me to project GEIT and asked me whether I would like to volunteer.

I jumped at the opportunity and a few days later, took my first session at Azmane High School (17th November). Following that, I went to St. Bartholomew’s High School (19th & 20th November) and Dayanand High School (21st November).

It was amazing to see so much enthusiasm in the students, many of whom share a passion for coding. The excited grins on their faces on accomplishing the challenges thrown to them, was priceless.

I thoroughly enjoyed the interactive sessions at all the schools and met some wonderful people. It was an incredible learning experience and one of my most well-spent vacations.

Thank you GEIT, for giving me the opportunity to be part of this revolution.

Special thanks to Sangeeta Naik, Vincent Toscano, Jessica D’Abreo, Mona Parras and Pradeep Gaonkar.

Press conference at Goa Chamber of Commerce & Industry at the end of the 10-day camp