By continuing to use this site, you agree to our use of cookies. Find out more
Forum sponsored by:
Forum sponsored by Forum House Ad Zone

Prototype Boards

All Topics | Latest Posts

Search for:  in Thread Title in  
Phil Grant10/10/2018 20:46:49
107 forum posts
21 photos

I've had a look at some old code that I used that used interrupts and as I can see you setup the interrupts in the setup part of the code

attachInterrupt(0, Start, FALLING);
attachInterrupt(1, Stop, FALLING);

0 = pin 2, 1 = pin 3, "start" and "stop" are the names of the functions that get called when the interrupts are triggered and the falling indicates that the level goes from high to low to trigger the interrupt.

Peter Bell10/10/2018 22:49:53
399 forum posts
167 photos

Thanks for the replies, very helpful.

This is part of the code that I want count with from the sensor. It will eventually have more zones and successfully looped using the small delay when I tried it on my breadboard.

It is my first attempt with Arduino and although I'm sure it could be improved no end I was pleased to get it running with some help from a friend.

Due to bringing the wrong memory stick with me I do not have the version where I tried incrementing using attached interrupt, sorry.

I did think that perhaps I should practice adding attached interrupt to blink as pratice when I return?

#include <Wire.h> // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address

//int ledPin = 13;
int ledPin = 2;
int switch1 = 3;
int count;

void setup()
{
Serial.begin(9600); // Used to type in characters
lcd.begin(16, 2);// set up the LCD's number of columns and rows:
lcd.setCursor(2, 0); // Print a message to the LCD.
lcd.print("Rail Squirt";
delay (2000);
lcd.setCursor(0,1);
lcd.print(" by Peter Bell";
delay (2000);
lcd. clear();
lcd.print(" Version 2.7M"; //Version
lcd.setCursor(2, 1);
lcd.print(" 10-10-18";
pinMode(ledPin, OUTPUT);
delay (4000);
lcd. clear();
delay(1000);
}
void loop()
{

Serial.begin(9600);
Serial.println(count);


lcd.setCursor(2, 0);
lcd.print("Zone"; // ZONE 1 OFF
lcd.setCursor(9, 0);
lcd.print("1 OFF";

if (count > 155 && count < 175) {
digitalWrite(ledPin, HIGH);// output on

lcd. clear();
lcd.setCursor(2, 0);
lcd.print("Zone"; // ZONE 1 ON
lcd.setCursor(9, 0);
lcd.print("1 ON";
}
lcd.setCursor(9, 0);
lcd.print("8 ON";

if (count > 175 && count < 1500) {
digitalWrite(ledPin, LOW); //output off
lcd. clear();
lcd.setCursor(2, 0);
lcd.print("Zone"; // ZONE 8 OFF
lcd.setCursor(9, 0);
lcd.print(" END";

}

count ++ ;
lcd.setCursor(6,1);
lcd.print(count);
delay(200);

if (count == 1500) count = 0; //re-sets
lcd. clear();
}

duncan webster10/10/2018 23:01:44
5307 forum posts
83 photos
Posted by Phil Grant on 10/10/2018 20:46:49:

I've had a look at some old code that I used that used interrupts and as I can see you setup the interrupts in the setup part of the code

attachInterrupt(0, Start, FALLING);
attachInterrupt(1, Stop, FALLING);

0 = pin 2, 1 = pin 3, "start" and "stop" are the names of the functions that get called when the interrupts are triggered and the falling indicates that the level goes from high to low to trigger the interrupt.

I think to comply with preferred method this should be

attachInterrupt(digitalPinToInterrupt(2), Start, FALLING);

attachInterrupt(digitalPinToInterrupt(3), Stop, FALLING);

Phil Grant10/10/2018 23:08:43
107 forum posts
21 photos
Posted by duncan webster on 10/10/2018 23:01:44:
Posted by Phil Grant on 10/10/2018 20:46:49:

I've had a look at some old code that I used that used interrupts and as I can see you setup the interrupts in the setup part of the code

attachInterrupt(0, Start, FALLING);
attachInterrupt(1, Stop, FALLING);

0 = pin 2, 1 = pin 3, "start" and "stop" are the names of the functions that get called when the interrupts are triggered and the falling indicates that the level goes from high to low to trigger the interrupt.

I think to comply with preferred method this should be

attachInterrupt(digitalPinToInterrupt(2), Start, FALLING);

attachInterrupt(digitalPinToInterrupt(3), Stop, FALLING);

Yes you are right, but on a nano it compiles and works fine using int.0 and int.1.

Peter Bell11/10/2018 08:57:51
399 forum posts
167 photos

Looks like interrupt is being well covered thanks. Unfortunately Unable to try anything at present but looking forward to it

The other method mentioned by Dave is “spin digitalRead() in a loop” Perhaps that could be an alternative as once the code has been activated by an impulse it runs then just sits waiting for the next pulse.Is there an example of that somewhere? That would help—-thanks Peter

Peter Bell11/10/2018 09:27:33
399 forum posts
167 photos

Forgot to say that the input is pretty slow, between 0–5hz

Phil Grant11/10/2018 09:34:12
107 forum posts
21 photos

I have some code that I wrote for an air rifle chronograph that detects a pellet breaking a beam then measuring the time taken before the second beam is broken then sending the time via bluetooth.

This code basically sits waiting for a pin to be triggered then does something then goes back to wait a again, you could probably adapt t his code, it's very simple really.

I have details on my blog here www.gadjet.co.uk

Edited By Phil Grant on 11/10/2018 09:34:40

Phil Grant11/10/2018 10:01:03
107 forum posts
21 photos

My chronograph code is measuring events around 200uS apart so it should be more than capable enough.

SillyOldDuffer11/10/2018 11:41:37
10668 forum posts
2415 photos

Well here's Pete's code modified to increment count whenever pin 3 is grounded.

Bit more complicated that it should be because I use a different version of the LiquidCrystal library and only have a 20x4 display.

Testing by tapping a lead from pin 3 to ground. It works, but as noted in the code, it detects contact bounce galore! Debouncing is a separate issue and, as the best way of fixing it depends on Pete's input circuit, I won't cover it in this post.

#include <Wire.h> // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>

// SoD : there are a few different LiquidCrystal_I2C libraries. Changed to use the one I have

// LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
LiquidCrystal_I2C lcd(0x3f,20,4);  // SoD's display has LCD address to 0x3f for a 20 chars x 4 line display

//int ledPin = 13;
int ledPin = 2;
int switch1 = 3;

volatile int count; // SoD: Changed to volatile.

void switch1InterruptServiceRoutine()
{
  // SoD: Executed when an interrupt is received on the attached pin
  // Note: code is potentially too simple for direct use with a mechanical switch
  //       because the ISR will trigger repeatedly if the switch contact bounces. (As they do!)  
  //       See 'debouncing' on web

  count++;
}

void setup()
{
  Serial.begin(9600); // Used to type in characters
  //lcd.begin(16, 2);// set up the LCD's number of columns and rows:
  lcd.init();  lcd.backlight(); // needed for SoD's version of the LiquidCrystal library

  lcd.setCursor(2, 0); // Print a message to the LCD.
  lcd.print("Rail Squirt";
  delay (2000);
  lcd.setCursor(0,1);
  lcd.print(" by Peter Bell";
  delay (2000);
  lcd. clear();
  lcd.print(" Version 2.7M"; //Version
  lcd.setCursor(2, 1);
  lcd.print(" 10-10-18";
  pinMode(ledPin, OUTPUT);

  delay (4000);
  lcd. clear();
  delay(1000);

  // SoD - register the interrupt service routine
  // Note 'FALLING' means that switch1 is normally HIGH. The interrupt is triggered whenever switch1 goes low
 
  pinMode(switch1, INPUT_PULLUP );  // SoD: make the interrupt pin normally HIGH to detect FALLING

  attachInterrupt( digitalPinToInterrupt( switch1 ), switch1InterruptServiceRoutine, FALLING );
}

void loop()
{
  // Serial.begin(9600); SoD: already declared in setup(), only needed once
  Serial.println(count);
 
  lcd.setCursor(2, 0);
  lcd.print("Zone"; // ZONE 1 OFF
  lcd.setCursor(9, 0);
  lcd.print("1 OFF";
 
  if (count > 155 && count < 175) {
    digitalWrite(ledPin, HIGH);// output on
    lcd. clear();
    lcd.setCursor(2, 0);
    lcd.print("Zone"; // ZONE 1 ON
    lcd.setCursor(9, 0);
    lcd.print("1 ON";
  }
  lcd.setCursor(9, 0);
  lcd.print("8 ON";
 
  if (count > 175 && count < 1500) {
    digitalWrite(ledPin, LOW); //output off
    lcd. clear();
    lcd.setCursor(2, 0);
    lcd.print("Zone"; // ZONE 8 OFF
    lcd.setCursor(9, 0);
    lcd.print(" END";
  }
 
  //  count ++ ; SoD: replaced by ISR
  lcd.setCursor(6,1);
  lcd.print(count);
 
  delay(200);   // SoD: may not be necessary, best to avoid delay() if possible.
 
  // if (count == 1500) count = 0; //re-sets
  if ( count >= 1500 ) count = 0;  // SoD: safer reset!  Interrupts mean count==1500 might be skipped.  
  lcd. clear();
}

 

Edited By SillyOldDuffer on 11/10/2018 11:51:36

Edited By SillyOldDuffer on 11/10/2018 11:52:51

Phil Grant11/10/2018 17:26:30
107 forum posts
21 photos

Just for interest I discovered a link to a site that uses blockly to graphically code for Arduino and other languages, this could be very useful for those not confident in using the Arduino IDE C code editor, this basically creates the code by dragging graphical block onto a sheet as required then paste to code into the Arduino IDE.

**LINK**

To use the editor click on the US flag on the left under 'blocklyduiuno"

Peter Bell11/10/2018 21:34:01
399 forum posts
167 photos

Dave, Many Thanks for adding the code and explanations, just trying to work my way through them on a WiFi hotspot thats worse than dial up used to be.

At present it wont verify with a mysterious message (at least to me!) "of expected '' before ';' token" on the first LCD print up from the end of the sketch. Cannot spot anything obvious--looks the same as the one I listed and that verifies ok--perhaps I've lost some some syntax somewhere?

Phil, thanks for the blockly info, never heard of that for Arduino before--I'll explore.

Not sure where all the smileys came from though.

Peter

SillyOldDuffer12/10/2018 09:31:52
10668 forum posts
2415 photos
Posted by Peter Bell on 11/10/2018 21:34:01:

...

At present it wont verify with a mysterious message (at least to me!) "of expected '' before ';' token" on the first LCD print up from the end of the sketch. Cannot spot anything obvious--looks the same as the one I listed and that verifies ok--perhaps I've lost some some syntax somewhere?

...

Not sure where all the smileys came from though.

Hi Peter,

It's the curse of the smileys. The forum's editor 'helps' by converting the character strings once used to make text smileys and the like into emoticons. In the good old days before graphics a winky was a colon followed by a right bracket. Trouble is these combinations appear in computer source. As the editor also applies other officious format rules (like removing white-space on the left), it's hard to publish computer source code without having it subtly mangled!

Here's a dropbox link to the code I ran on my Nano. Note that you need to get rid of the changes I made to suit my particular version of LiquidCrystal which differs in the way displays are initialised.

Dave

Neil Wyatt12/10/2018 14:23:31
avatar
19226 forum posts
749 photos
86 articles
Posted by SillyOldDuffer on 12/10/2018 09:31:52:

It's the curse of the smileys. The forum's editor 'helps' by converting the character strings once used to make text smileys and the like into emoticons. I

Sadly, it appears to be spreading to other forums

Neil

Mark Rand12/10/2018 18:38:41
1505 forum posts
56 photos

That's alright. Just use uuencode laugh.

Edited By Mark Rand on 12/10/2018 18:40:57

Peter Bell12/10/2018 21:58:48
399 forum posts
167 photos

Hi Dave,

I must admit I thought that cut and past was just that, never realised what the editor was doing by tangling things around like that, another lesson learned.

The drop version works perfectly once I restored my lcd so many thanks for your help, still untangling what its all doing but its great to be learning and making progress at the same time. The switch bounce is horrendous but at least the serial numbers agrees with the lcd. The software solutions look very involved in the versions found so far so I'll try adding some r&c to see that the effect is. It may be ok in real life as I'm using a proximity sensor but I dont know what the rise time is yet.

You mentioned earlier "spin digitalRead() in a loop until a pulse is detected, then count it." as an alternative to attachinterrupt, could you point me to some info on it? Thanks

Peter

Phil Grant13/10/2018 10:57:22
107 forum posts
21 photos
Posted by Peter Bell on 12/10/2018 21:58:48:

You mentioned earlier "spin digitalRead() in a loop until a pulse is detected, then count it." as an alternative to attachinterrupt, could you point me to some info on it? Thanks

Peter

 

Peter,

Here is some code I wrote to check for a pin going low then counting microseconds before another pin goes low and then sending the value out over serial.

This code sits in the "wait state" (Spinning?) until the pin goes low it then changes to another "monitor state"

Please ask any questions you might have, I hope this is sort of what you're after.

/*
Sketch to measure the time in uSeconds between two IR sensors being triggered
and sending the result to the serial port.
Use with the PC application to display results
 
Version 1.00
Phil 25/04/13
*/
#define Trip_in_1 2 //set light Trigger 1 to pin D2
#define Trip_in_2 3 //set light Trigger 2 to pin D3
#define WAIT_STATE 0
#define MONITOR_STATE 1
#define OUTPUT_STATE 2
 
unsigned long Trigger_1 = 0;
unsigned long Trigger_2 = 0;
volatile unsigned int current_state = WAIT_STATE;
char my_oldSREG; //to hold status register while ints are disabled
unsigned long SensDist = 196850; //Distance between sensors in feet *1000000 60mm
unsigned long duration = 0; // time between triger 1 and 2
volatile boolean is_timeout = false;
 
 
void setup () {
//Serial.begin(38400);
Serial.begin(9600); // for raw un programmed BT board
Serial.println("Chrono SW Ver 1.00";
pinMode(Trip_in_1, INPUT);
pinMode(Trip_in_2, INPUT);
digitalWrite(Trip_in_1, HIGH); //turn on pullup resistor
digitalWrite(Trip_in_2, HIGH);
reset_variables();
 
}
 
 
void loop () {
switch (current_state) {
case WAIT_STATE:
if(digitalRead(Trip_in_1)==LOW) {
Trigger_1 = micros();
current_state = MONITOR_STATE;
}
break;
case MONITOR_STATE:
while(digitalRead(Trip_in_2)==HIGH); //loop until the Trigger goes LOW && !is_timeout
if(!is_timeout)
Trigger_2 = micros();
current_state = OUTPUT_STATE;
break;
case OUTPUT_STATE:
//if (Trip2 > Trip1) {
output_serial_info();
reset_variables();
current_state = WAIT_STATE;
//}
break;
}
}
 
void output_serial_info() {
 
 
// Serial.print("Duration\t";
Serial.println((Trigger_2 - Trigger_1));
//Serial.println(" uS";
}
 
void reset_variables() {
Trigger_1 = 0;
Trigger_2 = 0;
//is_timeout = false;
}
 

Edited By Phil Grant on 13/10/2018 10:58:15

SillyOldDuffer14/10/2018 17:15:04
10668 forum posts
2415 photos
Posted by Peter Bell on 12/10/2018 21:58:48:

Hi Dave,

...

You mentioned earlier "spin digitalRead() in a loop until a pulse is detected, then count it." as an alternative to attachinterrupt, could you point me to some info on it? Thanks

Peter

 

Hi Peter,

I've modified your code to show how it's done. It's on Dropbox.

Phil's example is more complicated because it does some software debouncing as well.

Depending on the application, it's often easier to provide hardware debouncing. The simplest method is just to put a capacitor (about 100nF not critical) across the switch contacts. It prevents 'FALLING' or 'LOW' being detected until the switch has been held down for several milliseconds, which tends to eliminate bounce. For more demanding applications you could wire up an NE555 as a debouncer, or a comparitor, - even better - a Schmitt Trigger chip. Much depends on what you're doing and how bad the switch is.

A very simple software debouncer might change the spin loop in the example based on your code to look like this:

// Spin waiting for input

while ( true ) {
if ( digitalRead( switch1 ) == LOW ) {
delay(50);
if (digitalRead( switch1 ) == LOW )
break;
}
}
// To get here the switch was operated
count++;

All it does is insist on two reads detecting LOW inside a time window before counting.

Debouncing is such a common problem that there are a few Arduino libraries in the Library Manager to provide software debouncing. I've tried Bounce2 - it's much smarter and more general than my simple example, for example it can manage several switches, but you might prefer one of the others. Bit of a learning curve with them.

Dave

 

Edited By SillyOldDuffer on 14/10/2018 17:15:43

Neil Wyatt14/10/2018 17:48:45
avatar
19226 forum posts
749 photos
86 articles

My preferred way of dealing with bounce is to use interrupt routines to set a flag and not re-enable them until I've dealt with the switch routine.

This enables me to deal with inputs when and where I want to without affecting time-critical processes with long interrupt routines.

If you use inline switch detections, it's usually easiest to plan your code so you don't test for a second switch condition twice within the bounce period.

Neil

Peter Bell14/10/2018 20:47:58
399 forum posts
167 photos

Hi Dave,

Thanks for all that, your description on debounce sounds logical. Yes a 100nf almost fixes it, adding a 1k resistor in series completely cures it as far as I can see. I'll have a look at the bounce libraries, a quick search reveals a lot to choose from.

Thanks also for the spin, makes sense apart from the syntax I'm afraid. The curly brackets with the semicolon inside are used to end a statement according the reference? { ; } I'm sure there's a simple explanation!

// Spin waiting for input

while ( digitalRead( switch1 ) == HIGH ) {
// Do nothing
;
}

Also adding a LOW digital read version first stops it just rolling through so that it increments each complete input cycle, what is the advantage of interrupt which (to me!) appears to be doing the same job?

Peter

Peter Bell14/10/2018 20:49:03
399 forum posts
167 photos

Thanks Neil, I'll have to work on that one once I get my head around the present learning!

Peter

All Topics | Latest Posts

Please login to post a reply.

Magazine Locator

Want the latest issue of Model Engineer or Model Engineers' Workshop? Use our magazine locator links to find your nearest stockist!

Find Model Engineer & Model Engineers' Workshop

Sign up to our Newsletter

Sign up to our newsletter and get a free digital issue.

You can unsubscribe at anytime. View our privacy policy at www.mortons.co.uk/privacy

Latest Forum Posts
Support Our Partners
cowells
Sarik
MERIDIENNE EXHIBITIONS LTD
Subscription Offer

Latest "For Sale" Ads
Latest "Wanted" Ads
Get In Touch!

Do you want to contact the Model Engineer and Model Engineers' Workshop team?

You can contact us by phone, mail or email about the magazines including becoming a contributor, submitting reader's letters or making queries about articles. You can also get in touch about this website, advertising or other general issues.

Click THIS LINK for full contact details.

For subscription issues please see THIS LINK.

Digital Back Issues

Social Media online

'Like' us on Facebook
Follow us on Facebook

Follow us on Twitter
 Twitter Logo

Pin us on Pinterest

 

Donate

donate