Ch-13 Design of Taxi Meter using Arduino NANO

13.1 Introduction
1. What is a Taxi Meter? A Taxi Meter is an electronic instrument (Fig-13.4) which is fitted with a rented Taxicab to record: Distance traveled, Waiting time, and Fare. These are the minimum features that a Taxi Meter should have.

2. Features of a Taxi Meter: Apart from the above mentioned three features, the Taxi Meter can have many other features of which the two most important are: Real Time Clock to know the time of the day, and a Printer to get the hard copy of the journey details. The other optional features that can be added with the meter are:

Radio link for dispatching trip information to supervisor.
Interaction with GPS systems to receive security assistance during danger/accident.
Seat sensors that detect the presence of passengers.
Credit or prepaid card support.
Extra charge for luggage.
Speed of the Taxicab.
Diagnostics support like determining the ageing of the wheel/tire and LED test.

3. Authorized Tariffs in Bangladesh:
Flat Fare for the 1st 2 Km journey : Tk 40.00
Fare for next each Km distance traveled after 1st 2 Km : Tk 12.00
Distance Update (Designer's option): 10m
Waiting Time fare for each 1-min (60-sec) waiting: Tk 2.00
Fare Update for each 200m distance traveled after 1st 2 Km (Tk 12.00/5): Tk 2.40
Advance Fare (fare Update) for 200m after 1st 2Km crossing (1/5th of 1 Km): Tk 2.40
Calculation Reference: Distance

4. Conceptual Pictorial view of 3-window Taxi Meter (with diagnostic support)
Fig-13.1 is a line sketch that reflects the idea of the "to be Taxi Meter" perceived at conceptual level looking at the functioning of the real Taxi Meters in the CNGcabs, talking with the people who repair these meters, and standard design specs.

For the development and testing of the Taxi Meter, I have used Arduino NANO Learning Kit and C/C++/Arduino Language in my own style of creativity The physical implementation of this conceptual level is given in Fig-13.3.

taxiMeter-0.png
Figure-13.1: Conceptual pictorial view of 3-window Taxi Meter (with diagnostic support)

(1) The transducer is attached with the gearbox of the Taxicab. The "real transducer" (Fig-13.4) that is being used in this project is from a particular company, and it produces about 16 pulses (known as WTP for Wheel Turning Pulse) when the taxicab moves 10 m distance.

(2) The meter has three windows:
DDM Meter (Digital Distance Meter) to record distance traveled by the taxicab at every 10 m.
DFM Meter (Digital Fare Meter) to record total fare including the flat fare of Tk 40.00 for the 1st 2 Km, and
DWM Meter (Digital Waiting time Meter) to record waiting time in the trip (max: 99 Min 99 Sec).

(3) For development and testing of the Taxi Meter, we will be using 555-based (Fig-13.2) 1 Hz oscillator instead of "real transducer" to simulate WTP pulses.


Figure-13.2: 555-based low frequency oscillator to simulate WTPs

(4) When the taxicab has not yet been hired and the driver has pressed down the RST button, the DDM Digital Distance Meter), DFM (Digital Fare Meter), and DWF (Digital Waiting Time Meter) will show 0s. That is:
DFM : 0.00 Km
DFM : 0.00 Tk
DWM : 0.00 Mn //(0 minute and 00 second)

(5) After the taxicab has been hired and the driver has pressed the "HRD (Hired)" button, the digital meters will show:
DFM : 0.00 Km
DFM : 40.00 Tk //Flat fare for the 1st 2 Km or 20 min waiting time or of combination
DWM : 0.00 Mn //(0 minute and 00 second)

(6) The taxicab has started moving, the DDM advances by 10 m. There will be no change in DFM meter until the taxicab has just crossed 2 Km distance. It is assumed that the taxicab has not encountered any waiting state in the trip. When the taxicab has just crossed the 2 Km distance, DFM is augmented by Tk 2.40 which is an advance payment to the driver for the cost of 200 m distance given the fare rate is Tk 12.00/Km. The meter readings are:
DFM : 2.00 Km
DFM : 42.40 Tk //40.00 + 2.40
DWM : 0.00 Mn (0 minute and 00 second)

5. Physical Pictorial view of 3-window Prototype Taxi Meter (with diagnostic support)
Taximeter-3.png
Figure-13.3: Physical pictorial view of 3-window prototype Taxi Meter (with diagnostic support)

6. Physical Pictorial view of 3-window Simplified Prototype Taxi Meter (no diagnostic support)
TaxiMeter-1.png
Figure-13.4: Physical Pictorial view of 3-window simplified prototype Taxi Meter (no diagnostic support)

Working Principle: (1) The green color gadget of Fig-13.4 is the transducer which is fitted with the gearbox of the Taxicab, and it generates about 16 pulses when the Taxicab moves by 10 m distance. These pulses are called WTP (wheel turning pulses), and they are accumulated by TC0 Module of the MCU to update DDM Meter (Digital Distance Meter) by 10 m.

(2) The flat fare for the first 2 km is Tk 40.00 and then the fare is Tk 12.00 for each km covered. The DFM Meter (Digital Fare Meter) accumulates/updates fare for each 200 m traveled which is Tk 2.40. When the Taxicab just crosses initial 2 km distance, the DFM shows a reading of Tk 42.40 (40.00 + 2.40) which means that the Taxi driver is paid an advance payment for the fare of 200 m; as a result, there is no chance for the driver to lose fare even the passenger gets down at any place.

(3) There is a fare for waiting time which is Tk 2.00 for each minute waiting. As the practical journey/trip is a combination of distance traveled and waiting time, the fare is always computed based on the combined effect of distance and waiting time; where distance is the reference. The DWM Meter (Digital Wait Meter) records the total waiting time happened in the trip (0.00 to 99.99 = 0 Min 0 Sec to 99 Min 99 Sec).

(4) There are three buttons on the face plate of the Taximeter of Fig-13.4 and these are:RESET, TOPAY, and HIRED. The functions of these buttons are:
a) RESET: The driver pushes this button to bring 0.00 into DDM, 0.00 into DFM, and 0.00 into DWM.
b) HIRED: The driver pushes this button when the Taxicab is hired. As a result, o.00 comes into DDM, 40.00 (as Flat Fare) on DFM, and 0.00 into DWM. This button will work only for once during the whole journey and after the rest button that brings Tk 0.00 in DFM.

c) TOPAY: the driver pushes this button at the end of journey. As a result, all activities of the Taxi Meter gets frozen. The display reading do not change. The passenger records the distance traveled, fare charged, and the waiting time. This button will work only when the taxicab is in "waiting state".

7. There could be three types of journey/trip for the taxicab and these are:
(1) Distance-drive (D-drive): There is no waiting in the trip. The whole fare is due to distance traveled and the flat fare.
(2) Time-drive (T-drive): There is no distance traveled. The whole fare is due to waiting time and the flat fare.
(3) Combined-drive (C-drive): This is the practical journey. The whole fare is due to the combined effect of distance traveled, waiting time, and flat fare.

8. Physical Pictorial view of 2-window Simplified Prototype Taxi Meter
In this meter, the Distance and the Waiting Time are shown on a single display unit (the Top one in Fig-13.5) on multiplexed basis. Thus, there is a saving of four display units and reduces the cost of the meter a little bit.
TaxiMeter-4.png
Figure-13.5: Physical pictorial view of 2-window simplified prototype Taxi Meter

9. Schematic Diagram of an Arduino NANO based 3-window Taxi Meter


Figure-13.6: Schematic Diagram of an Arduino NANO based 3-window simplified Taxi Meter of Fig-13.4

10. Pictorial view of the development Process of Arduino NANO based Taxi Meter
TaxiMeter-2.png
Figure-13.7: Pictorial view of the development process of Arduino NANO based Taxi Meter l

TaxiMeter-1.png

Taximeter-3.png

TaxiMeter-4.png

TaxiMeter-2.png

taxiMeter-0.png

1 Like

13.2 Analysis and Implementation of D-drive Journey
In this Section, we will analysis D-drive journey (Fig-13.29) of the Taxi Meter and then will write codes to update the DDM Meter and DFM Meter of Fig-13.6. In D-drive journey, the Taxicab does not suffer any "waiting time"; the whole journey is composed of only distance traveled.

1. Line Diagram for the D-drive journey of Taxi Meter
d-drive.png
Figure-13.29: Line Diagram for D-drive journey

working Principle: Flat fare Tk 40.00 remains unchanged for the 1st 2 Km. At 2 Km point, the driver is paid an advance of Tk 2.40 (cost of 200 m distance at fare rate of Tk 12.00/Km). When the current advance payment is exhausted, the driver is paid another advance of Tk 2.40; the process keeps going like this until the journey ends. The DDM keeps updating the distance traveled at 10 m interval; whereas, the DWM remains at 0.

2. Flow Chart representation for the line diagram of Fig-13.29.


Figure-13.30: Flow Chart representation of D-drive journey

Working Principle: (1) Flow Chart is a programming technique by which the solution of a problem is described using few pre-defined geometrical figures which are oval (for start/stop; entry/exit; execute/halt; suspend/resume), rectangle (for ALU and memory operations), diamond (for decision making), parallelogram (for IO operations), double sided rectangle (for subroutine call), arrow/flow line (for signal flow). Flow Chart shows interesting ways of creating codes for a sketch.

(2) It is chosen to advance the DDM by 10m. Initially, the DDM reading is 0.00 and then it will show: 0.010 ==> 0.01. The right-most digit will not be shown on DDM as it is always 0.

(3) In Fig-13.30, it is observed that a flag has been set at true state at LD9: when the Taxicab has just crossed the 2 Km point. The flag helps the sketch to understand if the Taxicab is still within 2 Km zone or beyond to update DFM by Tk 2.40 far each 200m distance traveled.

(4) In order to make fare calculation easier and convenient, 10m distance would be taken as "1 unit" or "1 DQ = 1 distance quanta".

(5) To determine that the Taxicab has crossed 2 Km (2000m = 200x10m = 200 DQ) distance, a 200 units of DQs are counted with the declaration of the following counter:

byte counterDQ = 0;   //initially zero

(6) After 2 Km distance cross point, the sketch will to count 20 units of DQs to determine that the Taxicab has traveled 200m (20x10m = 20 DQ) distance and now Tk 2.40 has to be added with DFM.

3. The Flow Chart of Fig-13.30 could be formulated by the following control structures/Pseudo Codes to update DDM and DFM during D-drive journey.

LD1:  Declare global variables as needed
void setup()
{
    LD2: Initialize variables as needed
}

void loop()
{
    LD3: If the Taxicab has not yet finished traveling 10m distance
    {
         LD4:  Refresh multiplexed display to avoid freezing the display into a single digit 
         goto LD3
    }
    LD5:  Increase DDM variable by 10m
    LD6:  Increase DQ counter by 1
    LD7:  if the Taxicab has not yet covered 2 Km distance
    {
        LD8: if the Taxicab has just arrived at 2 Km point with the just-passed 10m distnace
        {
             LD9:    Set flag to indicate that taxicab has just crossed 2 Km point
             LD10:  Increase DFM by Tk 2.40
             LD11:  Clear DQ counter
             goto LD3
        }
    } 
    else    //the Taxicab is outside 2 Km zone; check if 200m has gone and then add Tk 2.40 
    {
        LD12:  if the Taxicab has already reached at 2 Km point (flag == true)
        {
            //goto LD10 to add Tk 2.40 with DFM as advance fare for 200m and clear DQ counter
             LD10:  Increase DFM by Tk 2.40
             LD11:  Clear DQ counter
             goto LD3
        }
    }
}

4. Coding of Fig-13.30 in consultation with Pseudo Code of Step-3.
(1) Let us build the 555 oscillator on the breadboard.
(2) Connect the output of the oscillator at T0-pin of MCU via DPin-4 of Arduino UNO (Fig-13.6).
(3) The pulses coming from 555-based external oscillator are counted by TC0 Module (Fig-13.31) of ATmega328P MCU of the UNO Board. The TC0 Module operates as a "pre-set up counter". It starts counting up from a pre-set value and whenever it makes the "Full Count= 0x100 in hex = 256 in decimal)", the TOV0 flag of TIFR0 register becomes HIGH indicating that "full-count/roll-over/over-flow" has has happened.


Figure-13.31: Architecture of TC0 Module of ATmega328P MCU

5. Codes to advance DDM Meter when the TC0 has just received 16 pulses from external oscillator.
(1)//-- setup() function -------------------------------------------------------------------------

unsigned long DDM = 0000;  //range: 00000 - 99999; just remember position of decimal point
byte ccDDM[6]; //to hold cc-codes for the digits of DDM Meter
byte digitDDM[6]; //to hold digits/indices (0x00 - 0x09) for the digits of DP0-DP5 positions of DDM Meter
byte lupTable[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; //cc-code vs digit
                  //0,   1,    2,    3,    4,    5,    6,    7,    8,    9
void setup()
{
  Serial.begin(9600);
  initPORT();  //set directions of IO as needed
  initTC0(); //initialize TC0 as counter; TOV0 will set after counting 16 WTP
}

(2)//-- loop() function --------------------------------------------------------------------------

void loop()
{
  while (bitRead(TIFR0, TOV0) != HIGH) //TOV0 = HIGH means 16 WTP received
  {
    refreshDisplay();  //keep refreshing the multiplexed display until 16 WTPS are yet to receive 
  }
  bitSet(TIFR0, TOV0);   //clear the TOV0 flag
  TCNT0 = 0xF0;         //re-load preset value: 0xF0 (0x100 - 16 = 0x100 - 0x10 = 0xF0) = 240
  //-----------------------------------------
  advanceDDMBy10();     //add DDM by 10m; extract digits; get cc-code and save into ccDDM[] array
  suppressLeadingZero(); //remove the leading zeros of DDM Meter 000220 ==> 220==> 2.20
  placeDecimalPoint();     //put decimal point on DDM Meter to indicate meter part of Km; Fig-16.3
}

Working Principle: The MCU waits until TOV0 flag becomes HIGH to inform that the taxicab has traveled 10m distance. During this waiting time, the multiplexed display unit of the taxi meter (Fig-13.6) must be refreshed by calling the refreshDisplay() routine; otherwise, the display will not show the current distance, fair and waiting time. This display unit will be frozen to a single digit.

After exiting the while() loop, the MCU clears the TOV0 flag by putting HIGH at this bit position and then reload the CTNT0 by te pre-set value of 0xF0 (240); else, the TC) will begin counting form 0 and the over-flow event will happen after counting 256 WTPs which we do not desire. The over-flow event must happen after counting 16 WTPs.

6.//-- initPORT() function-----------------------------------------------------------------------

void initPORT()  
{
  //insert codes here
}

7.//--initTC0() function-------------------------------------------------------------------------

void initTC0()
{
  //insert code here
}

Hints:
(1) Consult data sheets for TC0 Module.
(2) Keep TC0 OFF.
(3) Hand calculate pre-set value (with clkTC0 as external source rising edge) so that over-flow occurs after counting 16 pulses from external source.

(4) Load pre-set value into TC0.
(5) Start (ON) TC0 Module with "external clocking" and "rising edge". Fig-13.30

8.//--refreshDisplay() function ---------------------------------------------------------------

void refreshDisplay() //transfer cc-codes of ccDDM[] into display port
{
 //insert code here
}

Assume that the value to be shown on DDM Meter is: 0002.35 ==> blank balnk blank 2. 3 5 (6-digit). The ccDDM array holds the cc-codes of the said 6-digit in the following array buffer (Fig-13.32). Note that ccDDM[3] contains a cc-code of 2 along with decimal point ( 2 + . = 1 101 1010).


Figure-13.32: Array buffer holding cc-codes of the digits of the display Meter of DDM Meter

Now, "refreshDisplay" refers to the continuous circulation of the contents of ccDDM array of Fig-13.31 into the respective display positions of the DDM Meter.

Hints: Send content of ccDDM[3] into DP3 position

byte x = ccDDM[3];  //cc-code in x = DB = 1101 1011 = p g f e d c b a
PORTB = x;  //lower 6-bit (a - f) has gone.
digitalWrite(6, bitRead(x, 6));   //g has gone
digitalWrite(7, bitRead(x, 7));   //p has gone
//-------------
PORTC = 0x03;       //cc3-pin active; 2. appears at DP3 position
//-------------
delay(5);               //wait for a while to see 2. at DP3 position

Use for() loop and send all 6-byte data into the display devices of DDM Meter (DP0 - DP5). It does not matter much that DP0-device is not physically installed to save a little bit of money.

9.//--advanceDDMBy10() function--------------------------------------------------------

void advanceDDMBy10()  //update DDM content (the variable: binaryDDM) by 10 m
{
 //insert code here
}

Hints:

unsigned long DDM; //assume present DDM = 0x000000EB (for 2.35 ==> 000235 decimal)
DDM = DDM + 1;   //DDM = 0x0000000D (13 decimal)
//----------------------------------------------------------------------------------
for(int i=0; i<6; i++)  //get the digits for the positions: DP5 DP4 DP3 DP2 DP1 DP0 of DDM Meter
{
   digitDDM[i] = binaryDDM%10;    //ccDDM[0] = 0x05; ccDDM[1] = 0x03; ccDDM[2] = 0x02; .......
   DDM = DDM/10;   //the quotinet
}
//-------
for(int i=0, j=5; i<6; i++, j--)   //
{
   ccDDM[i] = lupTable[digitDDM[j]];
}

Working Principle: (1) The DDM will advance by 10m which means: if the present reading of DDM = 2.35, (after traveling of 10m distance) the next show will be:
==> (2.36) How?
==> 2.350 + 0.010 ==> 2.35 + 0.01 ==> 235 + 01 ==> 235 + 1 ==> 236. This is to say:
DDM = DDM + 1; //DDM = 0x000000EC in binary/hex = 236 in decimal (point will be placed after 2-digit from right)

(2) Extract digits these digits: 0 0 0 2 3 6 for DP0 - DP5 positions from DDM variable of Step-a using %10 and /10 operators. As a result, we will get: 0x00, 0x00, 0x00, 0x02, 0x03, 0x06 and save them in the array named digitDDM[6].

(3) Use the values of Step-b and get the corresponding cc-codes from lupTable array and save them in the array named ccDDM[6].

(4)//-- suppressLeadingZero() function ---------------------------------------------------

void suppressLeadingZero()   //suppress all leading 0s except position DP3 of DDM
{
    //insert codes
}

Hints:
a) Assume that the current display of DDM : 0.12 ==> 012 //fixed point representation. Just remember the position of point (.) after 2-digit from right.

b) unsigned "long DDM" holds: 0x0000000C (12 in decimal); variable/memory location always holds binary
c) After adding 1 (0x01= 1) for 10m distance, DDM holds: 0x0000000D (13 decimal)
d) Digits extracted from DDM for DP0 - DP5 positions are:
0 0 0 0 1 3
==> 0x00, 0x00, 0x00, 0x00, 0x01, 0x03 using %10 and /10 operators.

e) Getting cc-cdoes for the digits of Step-iv and saving them in the array named ccDDM[]. byte ccDDM[6] holds: {0x3F, 0x3F, 0x3F, 0x3F, 0x31, 0x4F};// 0 0 0 0 1 3
f) After suppressing the three leading zeros, we have:
==> byte ccDDM[6] = {0x00, 0x00, 0x00, 0x3F, 0x31, 0x4F}; //0x00 is cc-code for 'blank' character

g) Display shows: 013 ==> 0.13
h) Codes:

if(ccDDM[0] == 0x3F
{
   ccDDM[0] = 0x00;    //0x00 is the cc-code for 'blank' character; nothing will appear at DP0 position
   if(ccDDM[1] == 0x3F)
   {
      ccDDM[1] = 0x00;  //DP1 is blank
      if(ccDDM[2] == 0x3F)
      {
         ccDDM[2] = 0x00; //DP2 is blank
      }
   }
}

10.//--placeDecimalPoint function --------------------------------------------------

void placeDecimalPoint()
{
     //insert codes
} //------------------------------------------------------------------------------------------------

11. Codes to add Tk 2.40 with DFM outside 2 Km zone for every 200m distance traveled.

byte counterDQ = 0x00;   //declare to hold 'Distance Quanta" which increments by 1 when 10m has gone
while(bitRead(TIFR0, TOV0) != HIGH)
{
    refreshDisplay();   //refresh display
}
bitSet(TIFR0, TOV);    //TOV0 flag is cleared
TCNT0 = 0xF0;            //re-load preset value
DQ++;
DDM = DDM + 1;         //update display
if(flag == false)
{
    if(counterDQ == 200) //2 Km has point
    {
        DFM = DFM + 240;   //4000 + 240 = 4240 ==> 42.40 //update DFM
        flag = true;
        counterDQ = 0;     //reset counter
    }
}
else
{
    if(counterDQ == 20)   //20x10 = 200m
    {
        DFM = DFM + 240;    //add Tk 2.40
        ounterDQ = 0;  //reset counter
    }
}

13.3 Analysis and Implementation of T-drive Journey
Write codes (for the Taxi Meter of Fig-13.6) in the form of control structures to perform the following tasks relating to the T-drive journey/trip (Fig-13.31) of the Taxi Meter.

T-drive.png
Figure-13.33: T-drive journey of Taxi Meter


Figure-13.34: Processing algorithm in the form of flow chart for the T-drive journey of Fig-13.33
... to be continued.

d-drive.png

1 Like

13.4 Analysis and Implementation of C-drive Journey
Write codes (for the Taxi Meter of Fig-13.6) in the form of control structures to perform the following tasks relating to the C-drive journey/trip (Fig-13.31) of the Taxi Meter.

C-driveX.png
Figure-13.35: C-drive journey of Taxi Meter

13.5 Questions and Answers
1. Refer to Fig-13.6 and check that HIRED button is pressed and then write codes to show 40.00 on the DFM Meter.

#define HIRED 3     //HIRED switch is connected at DPin-3
unsigned long DFM = 0;
while(digitalRead(HIRED) != LOW)     //HIRED button is not pressed
{
   refresDisplay();     //keep refreshing multiplexed display to avoid freezing to a single digit display
}
DFM = DFM + 4000;  //show Tk 40.00 on DFM
for(int i=0; i<6; i++)    //get digits: 0 0 4 0 0 0 for the DFM Meter
{
   digitDFM[i] = DFM%10; //digitDFM[0] = 0x00, digitDFM[1] = 0x00, digitDFM[2] = 0x00, digitDFM[3] = 0x04, 
   DFM = DFM/10;
}
for(int i = 0, j=5; i<6; i++, j--)
{
    ccDFM[i] = lupTable[digitDFM[j];   //get and store cc-codes for the digits of DFM Meter
}
suppressLeadingZeros();  //replace two leading zeros of DFM by blank character
placeDecimalPoint();       //place decimal point at DP3-position of DFM. ccDFM[3] = ccDFM[3]|0x80

... to be continued.

T-drive.png

… to be continued.

C-driveX.png

unoNanoY.png

More here

@TheMemberFormerlyKnownAsAWOL

So much gratitude for referring to that document which I have totally forgotten. This is a good shaped note which I can comfortably use in my 3 online classes on Ch-13 (System Design) particularly for the pandemic affected pupils of my varsity. The posts could be useful to the general users of the Arduino Forum.

Now, I enjoy the benefit of having posted my Arduino related learning materials into the Arduino Forum as very recently my hard disk has failed and I have lost many years' of documents though I have some backups but was not updated.

As for the report ?
Dunno what you really want to do...

Maybe lay them out as posts in the order YOU want and we can delete any intermittent disruptions that you call out as post #3,7,11 etc.to be deleted. Then your project will be as YOU want it.

Don't forget to leave some space size wise in each post for any updates.

Sample Test Questions:
//=======================================================
Ch-1 Fundamentals to Ch-13 Design of Taxi Meter using Arduino NANO
1. There are four basic tasks of a MCU. What are these tasks?
2. A variable is usually stored in the RAM area of the MCU. However, to save RA area, a user may store variables (which are not likely to get changed during program life) in Flash area. Write code to store 0x23 into flash memory.
Ans:

byte PROGMEM x = 0x23;

3. Write codes to blink L at DPin-13 at 1-sec interval using millis() function.
Ans:

byte output = HIGH;
void loop()
{
   unsigned long prMillis = millis();  //get elapsed time since you have uploaded sketch
   while(millis() - prMillis < 1000)     //1 sec has not yet elapsed
   {
       digitalWrite(13, output);         //L remains ON for 1-sec
   }
   output = !output;                      //now output = LOW
}

4. Rewrite sketch of Q1.3 by declaring the output variable within the loop() function.
5. Using for() loop, configure DPin-2 to 7 to work as output with internal pull-ups enabled.
6. Minimize number of lines for the following snippet.

void loop()
{
    byte n = Serial.avialable();
    if( n != 0)
    {
       char x = Serial.read();
       myData[i] = x;
       i++;
    }
}

7. The I2C address of a slave is given as 0x7E. Write codes to make a roll call for this device and then print message on the Serial Monition as appropriate.

8. Write codes to to get 32-bit IEEE-754 formatted value for the number 32.75.
9. Write proper codes so that the MCU can compute the correct value of i (3072) from the following expression:
i=4096*(1700-1400)/400

10.
//========================================================
Ch-2 Architecture
1. Pick up every block from within the following diagram and then write its name and function in the exercise book.


Figure-1:

2. Pick up every block from within the following diagram and then write its name and function in the exercise book.


Figure-2:

//========================================================

Ch-3 Digital IO Controller
1. Write a paragraph not more than 6 lines on the contents of the following diagram (Fig-3).
50lxy.png
Figure-3:

2. Write a paragraph not more than 9 lines on the contents of the following diagram (Fig-4).
pd2.png
Figure-4:
//========================================================

Ch-4 Analog to Digital Conversion Module
1. Pick up every block from within the following diagram and then write its name and function in the exercise book.


Figure-5:

Ch-8 Interrupt Structure of ATmega328P
Read the following diagram and answer to the questions.
intLM35.png
Figure-6:

1. Explain the meaning of "Interrupting the Microcontroller".
2. Write sketch so that whenever you interrupt the MCU by pressing K1, the MCU will acquire temperature signal from LM35 sensor and then will show it on the Serial Monitor with 2-digit after the decimal point.
Solution Hints:
(1) Configure DPin-2 as input with internal pull-up resistor.
(2) Make ISRINTZ() interrupt routine that will pass an indication to the loop() function that the MCU has received interrupt signal via DPin-2.

void ISRINTZ()
{
    flag = true;
}

(3) Acquire and display the temperature signal in the loop() function only once.

void loop()
{
   if(flag == true)
   {
       float myTemp = (float)100*(1.1/1023)*analogRead(A0);
       Serial.println(myTemp, 2);
       flag = false;
   }
}

(4) Do not forget to establish link between DPin-2 and ISRINTZ() routine and the active level of the interrupting signal. Do it in the setup() function by executing the following line:

attachInterrupt(digitalPinToInterrupt(2), ISRINTZ, LOW);

3. With reference to the following diagram (Fig-5), describe how does the IRQ-signal at DPin-2 cause the MCU to jump at the ISR routine named ISRINT0().


Figure-7:

//===============================================================

Ch-5 UART Port Based Serial Data Communication
5.1 Read the following diagram (Fig-1) and answer to the questions:
unoNanoY.png
Figure-8:

1. Write codes to create the SUART (2, 3) Port.
2. Write codes to receive Newline terminated 12 (decimal) from InputBox of Serial Monitor of UNO, receive it by the UNO, send it to NANO using SUART Port and then NANO will receive the data, save it into variable int x.
Hints: You can use the following method to receive characters from InputBox of Serial Monitor until Newline Character ('\n') is found and not saved.

byte m = Serial.readBytesUntil('\n', myData, 20);  //m = number of characters stored except '\n'

(1) Initialize everything as needed.
(2) Receive charcaters from Serial Monitor.

char myData[20];

byte n = Serial.available();
if(n != 0)
{
   byte m = Serial.readBytesUntil('\n', myData, 20); //detcet NewLine charcater but does not save
   myData[m] = '\0';  //insert null-byte as the last element in the array myData[]
   Serial.print(myData);     //Serial Monitor shows: 12
   SUART.print(myData);    //send 12 as 0x31 and 0x32
   SUART.write('\n');          //send Newline charcater as 0x0A
}

Slave Codes:

byte recData = (myData[0] << 4)|(myData[1] & 0x0F); //31=>10|02 => 12 = 00010011 binary
recData = (recData>>4)*0x0A + (recData & 0x0F)*0x01 ==> 0x0A + 0x02 = 0x0C ==> 12 decimal
Serial.print(recData, DEC);    //shows: 12 decimal

The above 1st two complicated lines of the above codes could be replaced by the following single line:

int recData = atoi(myData);   //myData[] array must be null-byte termination

3. You are sending a string of 10 charcaters from the InputBox of the Serial Monitor. Write sketch to receive only 5 of them and show it on the OutputBox of Serial Monitor.

4. Write meaning of the following code and then write expanded codes for it.

byte m = Serial.readBytesUntil('\n', myData, 20);  //m = number of characters stored except '\n'

Meaning: Check if the arrived character is Newline character ('\n'); if not, save it into array myData and continue up to 20 characters; if it is a newline character, then stop receiving/storing characters. Do not save the Newline character.

Expanded code:
[/b]

byte n = Serial.available()
if(n != 0)
{
   char x = Serial.read();
   if(x != '\n')
   {
       myData[i] = x;
       i++;
   }
   else
   {
       myData[i] = '\0'; //let there be a null byte as the last element in a char type array.
       Serial.print(myData);  //shows: 12
   }
}

//===============================================================

pd2.png

50lxy.png

Ch-6 I2C Bus Baser Serial Data Communication
Read the following diagram (Fig-2) and answer to the questions:
I2CBusFormation.png
Figure-9:

1. Write the codes that are to be executed at the both Master and Slave Sides to create the I2C Bus/Interface.

2. Assume that the Slave has initialized a variable with this string "Forum". Now, write necessary sketches so that the Master can issue command to the Slave to send the said string to Master and then Master will show the message in the OutputBox of its Serial Monitor.
Solution Hints:
A: Master Sketch
(1) Create I2C Bus.
(2) Initialize variables as needed.
(3) Roll call Slave.
(4) Issue "request command" to Slave in the setup() function.

byte m = Wire.requestFrom(slaveAddress, n);

n = number of bytes requested; put n = 10 (a reasonable value)
m = number of bytes actually received.

(5) Read the arrived charcaters from the Buffer and save them in an array and then show on SM.
[/b]

for(int i=0; i<m; i++)
{
   myData[i] = Wire.read();
}
myData[m] = '\0';  //insert null byte as the last element of the array
Serial.print(myData);

B: Slave Sketch
(1) Create I2C Bus.
(2) Initialize the variables as needed.
(3) Wait in the loop() function to have interruption when "request command" comes from Master.
(4) Go to this interrupt context: void sendEvent(){} and store the string "Forum" into Buffer by executing Wire.write() method.

void sendEvent()
{
   Wire.write(myData, sizeof(myData));   //char myData[] = "Forum";
}

3. Write sketch to check the presence of Slave of Fig-2 at address 0x52 and then show the following message on the Serial Monitor of Master. Your searching sketch should cover the address range: 0x08 to 0x7E

Slave Found at address: 0x52

/-------------------------------------------------------------
Ch-7 SPI Port Based Serial Data Communication
Read the following diagram and answer to the questions.

spi328x.png
Figure-10:

1. Write codes to create SPI Ports for both Master and Slave.

2. Write sketches for both Master and Slave to send 0x1234 from Master; the Slave will receive the data and will be displayed on the Serial Monitor of Slave.

3. When does SPIF flag get set (assume HIGH state).
//===============================================================

Ch-9 Timer/Counter Module of ATmega328P MCU
Read the following diagram (Fig-6) and answer to the questions.


Figure-11:

1. Compose 9 sentences to express the key information contained in Fig-6.
2. Write Pseudo Codes/Text Codes to initialize TC2 so that overflow event occurs at the elapse of 500 ms time period.
/--------------------------------------------------------------

Ch-10 Pulse Width Modulation using TC Modules of ATmega328P MCU
1. Write sketch to accomplish the followings with reference to the following figure.
(1) To generate 490 Hz PWM signal at DPin-3.
(2) The brightness of LED1 will be gradually changing as we gradually rotate/turn the pot (potentiometer) connected at Ch0 of the ADC via A0-pin.
pwmApp.png
Figure-12: Application of a PWM signal

(3) Analysis:
(a) Write the code that will impress 490 Hz PWM signal on DPin-3.

analogWrite(3, arg8);    //arg8 = 8-bit argument = 0 to 255

(b) arg8 of Step-(a) should be the value of ADC output.

unsigned int ADCOutput = analogRead(A0);  //ADCOutput = 0 - 1023

(c) arg8 of Step-(a) is 8-bit (0 to 255); but ADCoutput is 10-bit (0 to 1023). Therefore, arg8 can not be directly replaced by ADCOutput; the value of ADCOutput must be compressed/mapped into 0 to 255 using the following map() functin:

byte compressedValue = map(ADCOutput, 0, 1023, 0, 255);//variable, variable range, desired range
arg8 = compressedValue;

(d) Now, we have the following code which should be executed to impress PWM signal on Din-3. The duty cycle (ON-time) of the PWM will change as the pot value changes.

analogWrite(3, arg8);   //arg8 holds the compressed value of pot
==> analogWrite(3, compressedValue);
==> analogWrite(3, map(ADCOut, 0, 1023, 0, 255));
==> analogWrite(3, map(analogRead(A0), 0, 1023, 0, 255));
==> analogWrite(3, (map(analogRead(A0), 0, 1023, 0, 255)));

(4) The Sketch:

void setup()
{
     Serial.begin(9600);
     //pinMode(3, OUTPUT);    //no need; DPin-3 becomes output when analogWrite() is excuted
     analogReference(DEFAULT);   //Vref-point voltage of ADC is 5V
}

void loop()
{
    unsigned ADCOut = analogRead(A0);  //read pot voltage and get digital value in ADCOut
    byte compressedValue = map(ADCOut, 0, 1023, 0, 255);   //ADCOut value is compressed
    byte arg8 = compressedValue;
    ananlogWrite(3, arg8);      // 
}

(5) Slowly and steadily turn pot CW-CCW; observe that brightness of LED1 of Fig-10.3 changes/modulates.

2. Write a single line code for the 4-line codes of the loop() function of Q1.
//===============================================================

I2CBusFormation.png

spi328x.png

intLM35.png

cc4dRx1.png

SevSeg-master.zip (20.7 KB)

Ch-11 Peripheral Controllers and Devices
1. Write sketch to show the temperature signal of the LM35 sensor at 2-sec interval on the display unit of the Fig-11.1 using Library Functions/Methods. The prototypes and meanings of the methods could be found in the attached Library file (SevSeg-master.zip). Extract the zip file and then get the syntax rules and meaning of the methods. (You may take take help of the given sketch).
cc4dRx1.png
Figure-13:

#include "SevSeg.h"
SevSeg sevseg;
byte numDigits = 4;
byte digitPins[] = {A0, A1, A2, A3};//DP0, DP1, DP2, DP3
byte segmentPins[] = {8, 9, 10, 11, 12, 13, 6, 7};//a, b, c, ..., g, p from left
bool resistorsOnSegments = false;
byte hardwareConfig = COMMON_CATHODE;

void setup()
{
  Serial.begin(9600);
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(30);
  analogReference(INTERNAL);
}

void loop()
{
  unsigned long prMillis = millis();
  while (millis() - prMillis < 2000)//temp refreshed at 2-sec interval
  {
    sevseg.refreshDisplay();
  }

  float temp = 100 * ( 1.1 / 1023) * analogRead(A4);//31.76
  sevseg.setNumber(temp, 2);//decimal before 2-digit from right
}

/------------------------------------------------------

Ch-12 Sensors
1. Draw 4-wire SPI connection between 3.3V BME280 Sensor Breakout Board of Fig-12.13 and the UNO. The Breakout Board is without on-board Level Sifters and Voltage Regulator
BME280BreakOut.png
Figure-14: Breakout board without level sifter

Solution:
BME280spi.png
Figure-15: 4-Wire SPI Port connection of Fig-12.13 breakout board
//===============================================================

Ch-13 Design of Taxi Meter using Arduino NANO
//===============================================================
1. Read the following diagram of Fig-16 and answer to the questions:


Figure-16:

(1) Write the functions of the buttons: RST, HIRED, TO PAY, and LED TEST.
(2) Draw Line Diagram for the C-drive journey based on the data as shown on the display unit of the Taxi Meter.
(3) Write codes to describe the following D-drive journey.
d-drive.png
Figure-17:

... to be continued.

d-drive.png

1 Like