distributed*real.time*control systems - ulisboa · pdf filebasic*digital*input*–...

28
Distributed RealTime Control Systems Lecture 3 Embedded Systems Interfacing the Outer World 1

Upload: vuongdan

Post on 10-Mar-2018

215 views

Category:

Documents


2 download

TRANSCRIPT

Distributed  Real-­‐Time  ControlSystems

Lecture 3Embedded Systems

Interfacing the OuterWorld

1

Bibliography

• ATMEGA  328  Datasheet.• arduino.cc• Book:  – “Arduino Cookbook”,  2nd  Ed.– Michael  Margolis– O’Reilly,  2012

2

Interfaces• I/O

– Digital  I/O– Analog Input– PWM

• Serial  (USART)• SPI  • TWI

3

Digital  I/O• Port function (input/output)  is programmable by enablingand disabling

some  switches.  

4

Output  Modes

• Output  High • Output  Low

5

Input  Modes

• Input  floating (highimpedance)

• Input  with Internal Pull  Up

6

Digital  I/O  Registers

7

Basic  Digital  Output  -­‐ Driving LED’s• Caution!

– Source/Sink limits– 40mA  at 5Vcc

• Howmuch current passes  through the LED’s ?

8

const int led1  =  7;              //  LED1  connected   to  digital  pin  7const int led2  =  8;              //  LED2  connected   to  digital  pin  8const int rate  =  500;      //  Delay in  ms to  commute ledsint counter =  0;                      //  loop counter

void setup(){//  enable  output  on   the  led1  pinpinMode(led1,  OUTPUT);  //  enable  output  on   the  led2  pinpinMode(led2,  OUTPUT);//  initialize serial comms to  hostSerial.begin(9600);  }

void loop(){Serial.println(++counter);  //  print  rate  to  serial  monitordigitalWrite(led1,  HIGH);  //  set  the  LED1  ondigitalWrite(led2,  HIGH);  //  set  the  LED2  offdelay(rate);   //  wait  duration  digitalWrite(led1,  LOW);  //  set  the  LED1  offdigitalWrite(led2,  LOW);  //  set  the  LED2  ondelay(rate);}  

Basic  Digital  Input  – Reading  Switches

• Must  use  pull-­‐ups.

9

int inputPins[]  =  {2,3,4,5};  //  create  an  array  of  switch  inputsint ledPins[]  =  {10,11,12,13};   //  create  array  of  output  LEDs

void setup()  {for(int index =  0;  index <  4;  index++)        {pinMode(ledPins[index],  OUTPUT);   //  LED  as  outputpinMode(inputPins[index],  INPUT);   //  pushbutton  as  input  digitalWrite(inputPins[index],HIGH);  //  enable  pull-­‐ups

}}

void loop()  {for(int index =  0;  index <  4;  index++)        {int val =  digitalRead(inputPins[index]);  //  read  input  value//  check  if  the  switch  is  pressed  if  (val ==  LOW)   {//  turn  LED  on   if  switch  is  presseddigitalWrite(ledPins[index],  HIGH);  

}else {//  turn  LED  offdigitalWrite(ledPins[index],  LOW);  

}}

}

Digital  Inputs  – Switch Debouncing

10

//  debounce returns  true  if  the  switch  in  the  given  pin//  is  closed  and  stable

boolean debounce(int pin){boolean state;boolean previousState;//  store  switch  statepreviousState =  digitalRead(pin);  for(int counter=0;  counter  <  debounceDelay;   counter++)   {//  wait for  1  milliseconddelay(1);  //  read  the  pinstate  =  digitalRead(pin);  if(  state !=  previousState)                {//  reset  the  counter   if  the  state  changescounter  =  0;  //  and  save  the  current  statepreviousState =  state;  

}}//  here  when  the  switch  state  has  been  stable  //  longer  than  the    debounce periodreturn state;

}

Reading  Incremental  Encoders• Incremental  Rotary Encoders

have two quadrature channels.

• Direction of rotation can  bemeasured by detecting theraising/fallingedge of onechannel and checking the value ofthe other.

11

Reading  Incremental  Encoders

• Polling based solution

12

const int encPinA =  4;const int encPinB =  2;const int encSPR=16;    //Steps  Per  Revolution :  Depends on HWint angle =  0;    int val;    int encPos =  0;boolean encALast =  LOW;  //  remembers  the  previous  statevoid setup()    {pinMode(encPinA,   INPUT);pinMode(encPinB,   INPUT);digitalWrite(encPinA,  HIGH);                        //enable pull  upsdigitalWrite(encPinB,  HIGH);Serial.begin (9600);

}void loop()  {boolean encA =  digitalRead(encPinA);if  ((encALast ==  HIGH)  &&  (encA ==  LOW))   {(digitalRead(encPinB)  ==  LOW  ?  encPos-­‐-­‐ :  encPos++);angle=(encPos%encSPR)*360/encSPR;Serial.print (encoderPos);Serial.print ("  ");Serial.println (angle);

}encoderALast =  encoderA;

}

Reading  Incremental  Encoders• Interrupt Based Solution

• An Interrupt Service Routine (ISR)  can  associated to  a  falling edge on encoder channelA.

• Notes:  

– Only one ISR  can  run at a  time.– ISR  cannot have paramenters nor return values.– Variables that are  changed in  ISRs must  be

marked volatile.– Code in  the ISR  should be as  fast as  possible.– Serial  data  received while in  the ISR  may be lost.  – In  Arduino  UNO  you can  attach interrupts to  Pins  

2  and 3.– Function millis()   do  not increment while in  an

ISR.– Function delay()  does  not work inside and ISR.– Function delayMicroseconds() does  not use  

conters so it works.

13

const int encoderPinA =  2;const int encoderPinB =  4;int Pos,  oldPos;volatile int encoderPos =  0;   //maychange at any time

void doEncoder()   {   //ISR  for  FALLING  edge on channel Aif (digitalRead(encoderPinA)  ==  digitalRead(encoderPinB))encoderPos++;   //  count  up   if  both  encoder  pins  are  the  same

elseencoderPos-­‐-­‐;  //  count  down   if  pins  are  different

}void setup()    {pinMode(encoderPinA,   INPUT);pinMode(encoderPinB,   INPUT);digitalWrite(encoderPinA,  HIGH);digitalWrite(encoderPinB,  HIGH);    Serial.begin(9600);attachInterrupt(  digitalPinToInterrupt(  encoderPinA ),  

doEncoder,   FALLING);  }void loop()  {noInterrupts();                                                                                  //disable interruptsPos =  encoderPos;                                                                      //critical sectioninterrupts();                                                                                          //enable interruptsif(Pos !=  oldPos)      {Serial.println(Pos,DEC);oldPos =  Pos;  }

delay(1000);}

Reading  Pulse  Width Signal• Some  sensors communicate

output  via  Pulse  Width Duration.

• Arduino has a  function (pulseIn())  to  read pulse  durations.

• Example:  Parallax PING)))  Sonar.

14

const int pingPin =  5;void setup()  {Serial.begin(9600);

}void loop()    {int cm  =  ping(pingPin)  ;Serial.println(cm);delay(500);

}int ping(int pingPin)    {long duration,  cm;//  The  PING)))  is  triggered  by  a  HIGH  pulse  of  2  or  more  usec.pinMode(pingPin,  OUTPUT);digitalWrite(pingPin,  LOW);    delayMicroseconds(2);  digitalWrite(pingPin,  HIGH);  delayMicroseconds(5);digitalWrite(pingPin,  LOW);  pinMode(pingPin,   INPUT);duration =  pulseIn(pingPin,  HIGH);//  speed  of  sound  29  usec per  centimeter.cm  =  duration/29/2;return cm  ;

}

Analog Input• ARDUINO  UNO  ATMEL  328  ADC  

Characteristics

– 10-­‐bit  Resolution (0x000  – 0x3FF)

– 0.5  LSB  Integral  Non-­‐linearity

– ± 2  LSB  Absolute Accuracy

– 13  -­‐ 260  μs  Conversion Time

– Up to  76.9  kSPS (Up to  15  kSPS atMaximum Resolution)

– 6  Multiplexed Single  Ended Input  Channels

– Temperature Sensor   Input  Channel

– 0  -­‐ VCC  ADC  Input  Voltage Range

– Selectable 1.1V  ADC  ReferenceVoltage

– Voltage Range  Externally Selectable

• Free  Running or Single  Conversion Mode

• Interrupt on ADC  Conversion Complete

• Sleep Mode Noise  Canceler

• The  ADC  is  optimized  for  analog  signals  with  an  output  impedance  of  approximately  10  kΩ or  less.

15

Analog Input  Example• Light  depedent LED  

blinking.• Analog Read returns

values between 0  (min)  and 1024  (max).  

16

const int ledPin =  13;   //  LED  connected   to  digital  pin  13const int sensorPin =  0;  //  connect   sensor  to  analog  input  0

//  the  next  two  lines  set  the  min  and  max  delay  between  blinksconst int minDuration =  100;   //  minimumwait betweenblinksconst int maxDuration=  1000;   //  maximum  wait  between  blinks

void setup(){pinMode(ledPin,  OUTPUT);  //  enable  output  on  the  led  pinSerial.begin(9600);  //  initialize Serial}

void loop(){int rate  =  analogRead(sensorPin);  //  read  the  analog  input//scales  the  blink  rate  between  the  min  and  max   valuesrate  =  map(rate,  200,  800,  minDuration,  maxDuration);  rate  =  constrain(rate,  minDuration,maxDuration);  //  saturateSerial.println(rate);  //  print  rate  to  serial  monitordigitalWrite(ledPin,  HIGH);  //  set  the  LED  ondelay(rate);  //  wait  duration  dependent  on  light  leveldigitalWrite(ledPin,  LOW);  //  set  the  LED  offdelay(rate);}  

Measuring Voltages

• If voltages are  in  therange  [0  …  5]V,  they can  be measured directly.

• Otherwise we needvoltage dividers.

• Question:  How to  measure negative  voltages ?

17

Analog Output  via  PWM• AnalogOutput  can  be

emulated via  Pulse  WidthModulation.

• Arduino functionanalogWrite(pin,  value)  generates a  PWM  signal withfrequency~500Hz  and dutycycle proportional to  value.

• 0  <=  value <=  255

• pin  =  3,5,6,9,10,11

18

Modulate LED  Brightness via  PWM

• Fade  LED  brightness in  and out.

19

const int firstLed=  3;  const int secondLed =  5;const int thirdLed =  6;

int brightness =  0;int increment =  1;

void setup()  {   //  pins  driven  by  analogWrite do  not  need  to  be  declared  as  outputs}

void loop()  {if(brightness >  255)  {  increment  =  -­‐1;  //  count  down  after  reaching  255

}else if(brightness <  1)  {increment  =  1;  //  count  up  after  dropping  back  down  to  0

}brightness  =  brightness  +  increment;  //  write  the  brightness  value  to  the  LEDsanalogWrite(firstLed,  brightness);analogWrite(secondLed,  brightness);analogWrite(thirdLed,  brightness );delay(10);  //  mean  2.55  secs to  fade  up  or  down

}

Generating Frequencies

• Example:  Playing Tones

20

const int speakerPin =  9;    //  connect   speaker  to  pin  9const int pitchPin =  0;              //  frequency  of  the  toneconst int durationPin =  1;  //  duration  of  the  tone

void setup(){}

void loop(){int sensor0Reading  =  analogRead(pitchPin);  //  frequencyint sensor1Reading  =  analogRead(durationPin);  //  duration//  map  the  analog  readings  to  a  meaningful  rangeint frequency  =  map(sensor0Reading,  0,  1023,  100,5000);int duration =  map(sensor1Reading,  0,  1023,  100,1000);  tone(speakerPin,  frequency,  duration);  //  play  the  tonedelay(duration);  //wait  for  the  tone   to  finish

}

Driving High Power Devices• Arduino PINs can  

source/sink 40  mA atmost.

• To  drive  more  than 40mA:

– Use  amplification(transistors,  opamps,  etc).  Check datasheets.

– Use  multiple pins  (limitedto  400mA  if USB  power).  

21

Drive  a  DC  Motor  in  a  Single  Direction

• When the motor  does  not need to  reverse  direction,  a  simple PWM  drive  is as  follows:

22

Drive  a  DC  motor  in  both directions• To  drive  a  DC  motor  in  both

directions we need what istypically called a  H-­‐Bridge.

• Solutions:

– make a  H-­‐bridge  withdiscrete components.

– Buy an IC  with H-­‐bridges.

– Buy a  motor  shield for  arduino.

23

Drive  a  DC  motor  in  both directions

• Example with the L239  H-­‐Bridge.

24

const int enPin =  5;  //  H-­‐Bridge  enable pinconst int in1Pin  =  7;  //  H-­‐Bridge  input  pinsconst int in2Pin  =  4;void setup()  {Serial.begin(9600);pinMode(in1Pin,  OUTPUT);        pinMode(in2Pin,  OUTPUT);Serial.println("Speed  (0-­‐9)  or  +  -­‐ to  set  direction");

}void loop()  {if (  Serial.available())  {char ch =  Serial.read();if(isDigit(ch))  //  is  ch a  number?     {int speed  =  map(ch,  '0',  '9',  0,  255);analogWrite(enPin,  speed);

}else if (ch ==  '+')                {    //Rotate CWdigitalWrite(in1Pin,LOW); digitalWrite(in2Pin,HIGH);

}else if (ch ==  '-­‐')              {    //Rotate CCWdigitalWrite(in1Pin,HIGH);  digitalWrite(in2Pin,LOW);

}else {Serial.print("Unexpected character ");    Serial.println(ch);

}}

}

Hobbyist Servo  Motors• HobbyistServo  Motors use  a  

potentiometer attached to  a  DC  motor  shaft to  performposition control.

• The position reference iscommanded byPulse  PositionModulation PPM  and is notthe same as  the analogWrite()  PWM  signal.

• One can  use  the Servo  libraryto  implement the PPM  signals.

25

Drive  a  Hobby  Servo• External powermay be

required.  Do  not forget to  connect the Grounds.

• The Servo  libraryuses  Timer  1,  thus disables PWM  on pins  9  and 10.

26

#include <Servo.h>

Servo  myservo;   //  create servo  object to  control a  servoint angle  =  0;   //  variable  to  store  the  servo  position

void setup()    {myservo.attach(9,1000,2000);  //Servo  on  pin  9.  //Minimal  position  corresponds   to  1000microsec.  //Maximal    position  corresponds   to  2000microsec.//These  values  may  need  to  be  adjusted,//  depending  on  the  servo  model.

}

void loop(){for(angle  =  0;  angle  <  180;  angle  +=  1)          {  myservo.write(angle);  delay(20);  

}for(angle  =  180;  angle  >=  1;  angle  -­‐=  1)  {myservo.write(angle);  delay(20);  

}}

Devices with Different Voltage Levels• Do  not connect the ARDUINO  to  

devices with other voltage levels.  Thismay damage the I/O  ports.

• One way to  prevent damage is to  use  opto-­‐couplers.

• Example:  control a  TRS  camerashutter.  

27

//TAKE  20  PICTURES  AND  EXITint focus  =  4;   //optocoupler attached  to  focusint shutter  =  3;  //optocoupler attached  to  shutterlong  exposure  =  250;  //exposure  time  in  millisecondslong  interval  =  10000;   //time  between  shots,  in  millisecondsvoid setup()  {pinMode(focus,  OUTPUT);pinMode(shutter,  OUTPUT);for  (int i=0;  i<20;  i++)  //camera  will  take  20  pictures   {takePicture(exposure);  //takes  picturedelay(interval);  //wait  to  take  the  next  picture

}}void loop()  {      //NO  LOOP}void takePicture(long exposureTime){int wakeup  =  10;   //camera  take  time  to  wake  up  and  focus//adjust  this  to  suit  your  cameradigitalWrite(focus,  HIGH);  //wake  the  camera  and  focusdelay(wakeup);  //wait  for  it  to  wake  up  and  focusdigitalWrite(shutter,  HIGH);  //open  the  shutterdelay(exposureTime);  //wait  for  the  exposure  timedigitalWrite(shutter,  LOW);  //release shutterdigitalWrite(focus,  LOW);  //release  the  focus

}

Final  Note

Always read the documentation(datasheets)  of the devices to  

interface!

28