Added arduino libs

هذا الالتزام موجود في:
Mik6e6
2020-07-04 12:31:18 -04:00
ملتزم من قبل GitHub
الأصل 3d9b49e518
التزام dc9596f994
90 ملفات معدلة مع 9419 إضافات و0 حذوفات

عرض الملف

@@ -0,0 +1,47 @@
#include "CytronMotorDriver.h"
CytronMD::CytronMD(MODE mode, uint8_t pin1, uint8_t pin2)
{
_mode = mode;
_pin1 = pin1;
_pin2 = pin2;
pinMode(_pin1, OUTPUT);
pinMode(_pin2, OUTPUT);
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, LOW);
}
void CytronMD::setSpeed(int16_t speed)
{
// Make sure the speed is within the limit.
if (speed > 255) {
speed = 255;
} else if (speed < -255) {
speed = -255;
}
// Set the speed and direction.
switch (_mode) {
case PWM_DIR:
if (speed >= 0) {
analogWrite(_pin1, speed);
digitalWrite(_pin2, LOW);
} else {
analogWrite(_pin1, -speed);
digitalWrite(_pin2, HIGH);
}
break;
case PWM_PWM:
if (speed >= 0) {
analogWrite(_pin1, speed);
analogWrite(_pin2, 0);
} else {
analogWrite(_pin1, 0);
analogWrite(_pin2, -speed);
}
break;
}
}

عرض الملف

@@ -0,0 +1,44 @@
#ifndef CYTRON_MOTOR_DRIVER_H
#define CYTRON_MOTOR_DRIVER_H
#include <Arduino.h>
#include <stdint.h>
enum MODE {
PWM_DIR,
PWM_PWM,
};
class CytronMD
{
public:
CytronMD(MODE mode, uint8_t pin1, uint8_t pin2);
void setSpeed(int16_t speed);
protected:
MODE _mode;
uint8_t _pin1;
uint8_t _pin2;
};
/* class CytronMD10C : public CytronMD
{
public:
CytronMD10C(uint8_t pwmPin, uint8_t dirPin) : CytronMD(PWM_DIR, pwmPin, dirPin) {};
};
class CytronMD13S : public CytronMD
{
public:
CytronMD13S(uint8_t pwmPin, uint8_t dirPin) : CytronMD(PWM_DIR, pwmPin, dirPin) {};
}; */
#endif

عرض الملف

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 CytronTechnologies
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

عرض الملف

@@ -0,0 +1,60 @@
# Arduino Library for Cytron Motor Drivers
This library provides functions for Cytron Motor Drivers.<br>
Please refer to the examples on how to use the library.<br>
Connection to the motor driver is described in the comment section of the examples.
## Installation
1. Open the Arduino IDE, select `Sketch` -> `Include Library` -> `Manage Libraries...`.
2. Search for `Cytron Motor Drivers Library`.
3. Click `Install` to install the library.
4. Restart the Arduino IDE.
5. Examples can be opened in Arduino IDE from `File` -> `Examples` -> `Cytron DC Motors Library`.<br>
Please refer to the example list below for all the compatible motor drivers.
## Examples
### 1. PWM_DIR
This example shows how to drive a motor using PWM and DIR pins.<br>
PWM pin is used to control the speed of the motor while DIR pin is used to control the direction.<br>
<br>
This example only show how to drive a single motor for simplicity.<br>
For multi channels motor driver, all channels work the same way.<br>
**Compatible Motor Drivers:**
* [MD10C](https://www.cytron.io/p-md10c)
* [MD10-POT](https://www.cytron.io/p-md10-pot)
* [MD13S](https://www.cytron.io/p-md13s)
* [MD20A](https://www.cytron.io/p-20amp-6v-30v-dc-motor-driver)
* [MD30C](https://www.cytron.io/p-md30c)
* [SHIELD-MD10](https://www.cytron.io/p-shield-md10)
* [MDS160A*](https://www.cytron.io/p-mds160a)
* [MDS40B*](https://www.cytron.io/p-mds40b)
**Smart series motor driver needs to be configured as **Sign-Magnitude PWM Input** mode. Refer to user manual for more details.*
### 2. PWM_DIR_DUAL
This example shows how to drive 2 motors using PWM and DIR pins .<br>
PWM pin is used to control the speed of the motor while DIR pin is used to control the direction.<br>
**Compatible Motor Drivers:**
* [SHIELD-2AMOTOR](https://www.cytron.io/p-shield-2amotor)
* [SHIELD-3AMOTOR](https://www.cytron.io/p-shield-3amotor)
* [MDD10A](https://www.cytron.io/p-mdd10a)
* [FD04A](https://www.cytron.io/p-fd04a)
* [MDDS10*](https://www.cytron.io/p-mdds10)
* [MDDS30*](https://www.cytron.io/p-mdds30)
* [MDDS60*](https://www.cytron.io/p-mdds60)
**Smart series motor driver needs to be configured as **Sign-Magnitude PWM Input** mode. Refer to user manual for more details.*
### 2. PWM_PWM_DUAL
This example shows how to drive 2 motors using 4 PWM input pins (2 for each motor).<br>
Input A controls the motor speed in forward direction and Input B controls the motor speed in backward direction.<br>
**Compatible Motor Drivers:**
* [MAKER-DRIVE](https://www.cytron.io/p-maker-drive)
* [MDD03A](https://www.cytron.io/p-mdd03a)

عرض الملف

@@ -0,0 +1,60 @@
/*******************************************************************************
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTY AND SUPPORT
* IS APPLICABLE TO THIS SOFTWARE IN ANY FORM. CYTRON TECHNOLOGIES SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL
* DAMAGES, FOR ANY REASON WHATSOEVER.
********************************************************************************
* DESCRIPTION:
*
* This example shows how to drive a motor using the PWM and DIR pins.
* This example only shows how to drive a single motor for simplicity.
* For dual channel motor driver, both channel work the same way.
*
*
* CONNECTIONS:
*
* Arduino D3 - Motor Driver PWM Input
* Arduino D4 - Motor Driver DIR Input
* Arduino GND - Motor Driver GND
*
*
* AUTHOR : Kong Wai Weng
* COMPANY : Cytron Technologies Sdn Bhd
* WEBSITE : www.cytron.io
* EMAIL : support@cytron.io
*
*******************************************************************************/
#include "CytronMotorDriver.h"
// Configure the motor driver.
CytronMD motor(PWM_DIR, 3, 4); // PWM = Pin 3, DIR = Pin 4.
// The setup routine runs once when you press reset.
void setup() {
}
// The loop routine runs over and over again forever.
void loop() {
motor.setSpeed(128); // Run forward at 50% speed.
delay(1000);
motor.setSpeed(255); // Run forward at full speed.
delay(1000);
motor.setSpeed(0); // Stop.
delay(1000);
motor.setSpeed(-128); // Run backward at 50% speed.
delay(1000);
motor.setSpeed(-255); // Run backward at full speed.
delay(1000);
motor.setSpeed(0); // Stop.
delay(1000);
}

عرض الملف

@@ -0,0 +1,68 @@
/*******************************************************************************
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTY AND SUPPORT
* IS APPLICABLE TO THIS SOFTWARE IN ANY FORM. CYTRON TECHNOLOGIES SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL
* DAMAGES, FOR ANY REASON WHATSOEVER.
********************************************************************************
* DESCRIPTION:
*
* This example shows how to drive 2 motors using the PWM and DIR pins with
* 2-channel motor driver.
*
*
* CONNECTIONS:
*
* Arduino D3 - Motor Driver PWM 1 Input
* Arduino D4 - Motor Driver DIR 1 Input
* Arduino D9 - Motor Driver PWM 2 Input
* Arduino D10 - Motor Driver DIR 2 Input
* Arduino GND - Motor Driver GND
*
*
* AUTHOR : Kong Wai Weng
* COMPANY : Cytron Technologies Sdn Bhd
* WEBSITE : www.cytron.io
* EMAIL : support@cytron.io
*
*******************************************************************************/
#include "CytronMotorDriver.h"
// Configure the motor driver.
CytronMD motor1(PWM_DIR, 3, 4); // PWM 1 = Pin 3, DIR 1 = Pin 4.
CytronMD motor2(PWM_DIR, 9, 10); // PWM 2 = Pin 9, DIR 2 = Pin 10.
// The setup routine runs once when you press reset.
void setup() {
}
// The loop routine runs over and over again forever.
void loop() {
motor1.setSpeed(128); // Motor 1 runs forward at 50% speed.
motor2.setSpeed(-128); // Motor 2 runs backward at 50% speed.
delay(1000);
motor1.setSpeed(255); // Motor 1 runs forward at full speed.
motor2.setSpeed(-255); // Motor 2 runs backward at full speed.
delay(1000);
motor1.setSpeed(0); // Motor 1 stops.
motor2.setSpeed(0); // Motor 2 stops.
delay(1000);
motor1.setSpeed(-128); // Motor 1 runs backward at 50% speed.
motor2.setSpeed(128); // Motor 2 runs forward at 50% speed.
delay(1000);
motor1.setSpeed(-255); // Motor 1 runs backward at full speed.
motor2.setSpeed(255); // Motor 2 runs forward at full speed.
delay(1000);
motor1.setSpeed(0); // Motor 1 stops.
motor2.setSpeed(0); // Motor 2 stops.
delay(1000);
}

عرض الملف

@@ -0,0 +1,68 @@
/*******************************************************************************
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTY AND SUPPORT
* IS APPLICABLE TO THIS SOFTWARE IN ANY FORM. CYTRON TECHNOLOGIES SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL
* DAMAGES, FOR ANY REASON WHATSOEVER.
********************************************************************************
* DESCRIPTION:
*
* This example shows how to drive 2 motors using 4 PWM pins (2 for each motor)
* with 2-channel motor driver.
*
*
* CONNECTIONS:
*
* Arduino D3 - Motor Driver PWM 1A Input
* Arduino D9 - Motor Driver PWM 1B Input
* Arduino D10 - Motor Driver PWM 2A Input
* Arduino D11 - Motor Driver PWM 2B Input
* Arduino GND - Motor Driver GND
*
*
* AUTHOR : Kong Wai Weng
* COMPANY : Cytron Technologies Sdn Bhd
* WEBSITE : www.cytron.io
* EMAIL : support@cytron.io
*
*******************************************************************************/
#include "CytronMotorDriver.h"
// Configure the motor driver.
CytronMD motor1(PWM_PWM, 3, 9); // PWM 1A = Pin 3, PWM 1B = Pin 9.
CytronMD motor2(PWM_PWM, 10, 11); // PWM 2A = Pin 10, PWM 2B = Pin 11.
// The setup routine runs once when you press reset.
void setup() {
}
// The loop routine runs over and over again forever.
void loop() {
motor1.setSpeed(128); // Motor 1 runs forward at 50% speed.
motor2.setSpeed(-128); // Motor 2 runs backward at 50% speed.
delay(1000);
motor1.setSpeed(255); // Motor 1 runs forward at full speed.
motor2.setSpeed(-255); // Motor 2 runs backward at full speed.
delay(1000);
motor1.setSpeed(0); // Motor 1 stops.
motor2.setSpeed(0); // Motor 2 stops.
delay(1000);
motor1.setSpeed(-128); // Motor 1 runs backward at 50% speed.
motor2.setSpeed(128); // Motor 2 runs forward at 50% speed.
delay(1000);
motor1.setSpeed(-255); // Motor 1 runs backward at full speed.
motor2.setSpeed(255); // Motor 2 runs forward at full speed.
delay(1000);
motor1.setSpeed(0); // Motor 1 stops.
motor2.setSpeed(0); // Motor 2 stops.
delay(1000);
}

عرض الملف

@@ -0,0 +1,24 @@
#############################################
# Syntax Coloring Map For Cytron Motor Driver
#############################################
# Class
#############################################
CytronMD KEYWORD3
#############################################
# Methods and Functions
#############################################
setSpeed KEYWORD2
#############################################
# Constants
#############################################
PWM_DIR LITERAL1
PWM_PWM LITERAL1

عرض الملف

@@ -0,0 +1,9 @@
name=Cytron Motor Drivers Library
version=1.0.1
author=Cytron Technologies Sdn Bhd <support@cytron.io>
maintainer=Cytron Technologies Sdn Bhd <support@cytron.io>
sentence=Library for Cytron Motor Drivers.
paragraph=Provide examples on how to use the motor drivers.
category=Device Control
url=https://github.com/CytronTechnologies/CytronMotorDriver.git
architectures=*

تم حذف اختلاف الملف لأن الملف كبير جداً تحميل الاختلاف

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

عرض الملف

@@ -0,0 +1,487 @@
# EnableInterrupt
New Arduino interrupt library, designed for all versions of the Arduino.
Functions:
enableInterrupt- Enables interrupt on a selected Arduino pin.
disableInterrupt - Disables interrupt on the selected Arduino pin.
*_What's New?_
- Wed Sep 4 19:30:45 CDT 2019
- Version 1.1.0 of the library has been released. We add support for the ATmega2561 and 1281 chips,
with pinouts defined from the MCUdude/MegaCore project. Code donations by Kizmit99. Plus, a documentation
bugfix from Greg Bowler. Thanks, folks!
The EnableInterrupt library is an Arduino interrupt library, designed for
8-bit versions of the Arduino- at this writing, the Uno (and other ATmega328p-based
boards, like the mini), Due, Zero, Leonardo (and other ATmega32u4-based boards, like the
Micro), the Mega2560 (and other ATmega2560-based boards, like the MegaADK),
and for non-Arduino chips: the 644/1284p (Mighty1284, Sodaq Mbili and EnviroDIY Mayfly)
ATtiny 44/84, and ATtiny 45/85 (using DA Mellis' support files).
The library enables you to assign an interrupt to pins on your chip
that support them, and presents a common interface to all supported chips. This
means that on the Arduino Uno and Mega you don't give it an interrupt number, as per
http://arduino.cc/en/Reference/attachInterrupt. Rather, your first argument is a
pin number of a pin that's supported on that chip (see
https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#pin--port-bestiary ).
32-bit support for Due comes only in the form of a macro that enables your code
to be shared unchanged between 32- and 8-bit Arduinos. No further support for
32-bit Arduinos is planned.
## Download
See the https://github.com/GreyGnome/EnableInterrupt/wiki/Download page to
download the library.
## More Information
See the Wiki at https://github.com/GreyGnome/EnableInterrupt/wiki/Home .
For detailed usage information see https://github.com/GreyGnome/EnableInterrupt/wiki/Usage .
See the examples subdirectory in the distribution or in this Git site for code examples.
See the extras subdirectory in the distribution or in this Git site for License and Release Notes.
For a tutorial on interrupts, see
http://www.engblaze.com/we-interrupt-this-program-to-bring-you-a-tutorial-on-arduino-interrupts/
The posting gets into low-level details on interrupts.
IMPORTANT NOTE: In 0.9.2 I discovered a rather pernicious bug, wherein the library was setting the global interrupt enable bit. This could cause a serious and difficult-to-debug race condition, as it is not the job of the library to manage that bit. The chips come with interrupts enabled so existing code should not be affected, but if you were relying on that behavior note that it has changed. My thanks to http://gammon.com.au/interrupts (the 'How are interrupts queued?' section).
## ATmega Processor Interrupt Types
Note that the ATmega processor at the heart of the Arduino Uno/Mega2560/Leonardo/ATmega1284
has two different kinds of interrupts: “external”, and “pin change”.
For the list of available interrupt pins and their interrupt types, see the
PORT / PIN BESTIARY, below.
### External Interrupts
There are a varying number of external interrupt pins on the different
processors. The Uno supports only 2 and they are mapped to Arduino pins 2 and 3.
The 2560 supports 6 usable, the Leonardo supports 5, and the ATmega1284p supports 3.
These interrupts can be set to trigger on one of three signal values: RISING,
FALLING, or CHANGE (for both), or on LOW level. The triggers are interpreted by
hardware, so by the time your user function is running, you know exactly which
pin interrupted at the time of the event, and how it changed. On the other hand,
as mentioned there are a limited number of these pins.
### Pin Change Interrupts
On the Arduino Uno (and again, all 328p-based boards) and 644/1284-based boards,
the pin change interrupts can be enabled on any or all of the pins. The two
pins 2 and 3 on 328p-based boards, or three pins (2, 10, and 11) on the
1284-based boards support *either* pin change or external interrupts. On 2560-based
Arduinos, there are 18 pin change interrupt pins in addition to the 6 external
interrupt pins. On the Leonardo there are 7 pin change interrupt pins in addition
to the 5 external interrupt pins. See PIN BESTIARY below for the pin numbers and
other details.
Pin Change interrupts trigger on all RISING and FALLING (ie, "CHANGE") signal edges.
Furthermore, the processor's pins, and pin change interrupts, are grouped into
“port”s, so for example on the Arduino Uno there are three ports and therefore
only 3 interrupt vectors (subroutines) available for the entire body of 20 pin
change interrupt pins.
### The Library and Pin Change Interrupts
The foregoing means that not only do pin change interrupts trigger on
all pin transitions, but a number of pins share a
single interrupt subroutine. It's the library's function to make pin change interrupts
appear that each pin can support RISING, FALLING, or CHANGE, and each pin
can support its own user-defined interrupt subroutine.
When an event triggers an interrupt on any interrupt-enabled pin on a port, a
library subroutine ("interrupt handler", "interrupt service routine", or "ISR")
attached to that pin's port is triggered. It is up to the EnableInterrupt
library to set the proper port to receive interrupts for a pin, to determine
what happened when an interrupt is triggered (which pin? ...did the signal rise,
or fall?), to handle it properly (Did we care if the signal fell? Did we care
if it rose?), then to call the programmer's chosen subroutine (ISR). This makes the
job of resolving the action on a single pin somewhat complicated. There is a
definitive slowdown in the interrupt routine because of this complication.
So there is a significant*
time between when the interrupt triggers and when the pins are read to determine
what actually happened (rising or falling) and which pin changed.
So the signal could have changed by the time the pin's status is read, returning
a false reading back to your sketch. Therefore, these
pins are *not* suitable for fast changing signals, and under the right conditions
such events as a bouncing switch may actually be missed. Caveat Programmer.
If you're concerned about this, continue to read the following information and
make sure to read the wiki pages; especially see https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#atmega-processor-interrupt-types .
For a further review of this issue see
https://github.com/GreyGnome/EnableInterrupt/blob/master/Interrupt%20Timing.pdf
# USAGE:
## Basic Usage
*enableInterrupt*- Enables interrupt on a selected Arduino pin.
```C
enableInterrupt(uint8_t pinNumber, void (*userFunction)(void), uint8_t mode);
or
enableInterrupt(uint8_t interruptDesignator, void (*userFunction)(void), uint8_t mode);
The arguments are:
* pinNumber - The number of the Arduino pin, such as 3, or A0, or SCK. Note that
these are *not* strings, so when you use A0 for example, do not use quotes.
* interruptDesignator- very much like a pin. See below.
* userFunction - The name of the function you want the interrupt to run. Do not
use a pointer here, just give it the name of your function. See the example code
in the Examples directory.
* mode - What you want the interrupt to interrupt on. For Pin Change Interrupt
pins, the modes supported are RISING, FALLING, or CHANGE.
** RISING - The signal went from "0", or zero volts, to "1", or 5 volts.
** FALLING - The signal went from "1" to "0".
** CHANGE - The signal either rose or fell.
For External Interrupts, the same modes are supported plus the additional mode
of LOW signal level.
** LOW - The signal is at a low level for some time.
Each pin supports only 1 function and 1 mode at a time.
```
*disableInterrupt*- Disables interrupt on a selected Arduino pin.
```C
disableInterrupt(uint8_t pinNumber);
or
disableInterrupt(uint8_t interruptDesignator);
```
* interruptDesignator: Essentially this is an Arduino pin, and if that's all you want to give
the function, it will work just fine. Why is it called an "interruptDesignator", then? Because
there's a twist: You can perform a bitwise "and" with the pin number and PINCHANGEINTERRUPT
to specify that you want to use a Pin Change Interrupt type of interrupt on those pins that
support both Pin Change and External Interrupts. Otherwise, the library will choose whatever
interrupt type (External, or Pin Change) normally applies to that pin,
with priority to External Interrupt.
* The complexity is because of pins 2 and 3 on the ATmega328-based Arduinos, and pins 2, 10,
and 11 on 1284-based boards. Those are the only pins on the processors supported by this
library that can share External or Pin Change Interrupt types. Otherwise, each pin only supports
a single type of interrupt and the PINCHANGEINTERRUPT scheme changes nothing. This means you can
ignore this whole discussion for ATmega2560, ATmega32U4, or SAM3X8E (Due)-based Arduinos.
It is possible to change the user function assigned to an interrupt after enabling it (if you
want). Later in your code simply disable the interrupt and enable it with a different function.
## Determine the Pin That Was Interrupted
There is a facility in the library to identify the most recent pin that triggered an interrupt. Set the following definition '''before''' including the EnableInterrupt.h file in your sketch:
```
#define EI_ARDUINO_INTERRUPTED_PIN
```
Then, the ATmega chip will set a variable with every interrupt, and you can query it to find which pin interrupted your sketch. The variable is arduinoInterruptedPin and it is of type uint8_t.
See the https://github.com/GreyGnome/EnableInterrupt/wiki/Usage wiki page for more information.
# PIN / PORT BESTIARY
Theoretically pins 0 and 1 (RX and TX) are supported but as these pins have
a special purpose on the Arduino, their use in this library has not been tested.
## Summary
### Arduino Uno/Duemilanove/etc.
Interrupt Type | Pins
-------------- | --------------
External | 2 3
Pin Change | 2-13 and A0-A5
### Arduino Mega2560
Interrupt Type | Pins
-------------- | --------------
External | 2 3 and 18-21
Pin Change | 10-15 and A8-A15 and SS, SCK, MOSI, MISO
### Arduino Leonardo
Interrupt Type | Pins
-------------- | --------------
External | 0-3 and 7
Pin Change | 8-11 and SCK, MOSI, MISO
### Mighty 1284, Sodaq Mbili, EnviroDIY Mayfly
Interrupt Type | Pins
-------------- | --------------
External | 2 10 11
Pin Change | 0-31 (aka: 0-23 and A0-A7)
## Details
### Arduino Uno
<pre>
Interrupt Pins:
Arduino External Arduino Pin Change Arduino Pin Change
Pin Interrupt Pin Interrupt Pin Interrupt
Port Port Port
2 INT0 PD2 2 PCINT18 PD2 A0 PCINT8 PC0
3 INT1 PD3 3 PCINT19 PD3 A1 PCINT9 PC1
4 PCINT20 PD4 A2 PCINT10 PC2
5 PCINT21 PD5 A3 PCINT11 PC3
6 PCINT22 PD6 A4 PCINT12 PC4
7 PCINT23 PD7 A5 PCINT13 PC5
8 PCINT0 PB0
9 PCINT1 PB1
10 PCINT2 PB2
11 PCINT3 PB3
12 PCINT4 PB4
13 PCINT5 PB5
</pre>
### Leonardo Pins LEONARDO
<pre>
Interrupt pins:
Arduino Arduino
Pin External Pin Pin Change
Interrupt Interrupt
Port Port
3 INT0 PD0 8 PCINT4 PB4
2 INT1 PD1 9 PCINT5 PB5
0 INT2 PD2 10 PCINT6 PB6
1 INT3 PD3 11 PCINT7 PB7
7 INT6 PE6 SCK/15 PCINT1 PB1
MOSI/16 PCINT2 PB2
MISO/14 PCINT3 PB3
on ICSP:
SCK/15: PCINT1 (PB1)
MOSI/16: PCINT2 (PB2)
MISO/14: PCINT3 (PB3)
// Map SPI port to 'new' pins D14..D17
static const uint8_t SS = 17;
static const uint8_t MOSI = 16;
static const uint8_t MISO = 14;
static const uint8_t SCK = 15;
// A0 starts at 18
</pre>
### ATmega2560 Support
<pre>
External Interrupts ------------------------------------------------------------
The following External Interrupts are available on the Arduino:
Arduino
Pin PORT INT ATmega2560 pin
21 PD0 0 43
20 PD1 1 44
19 PD2 2 45
18 PD3 3 46
2 PE4 4 6
3 PE5 5 7
n/c PE6 6 8 (fake pin 75) **
n/c PE7 7 9 (fake pin 76)
Pin Change Interrupts ----------------------------------------------------------
ATMEGA2560 Pin Change Interrupts
Arduino Arduino Arduino
Pin PORT PCINT Pin PORT PCINT Pin PORT PCINT
A8 PK0 16 10 PB4 4 SS PB0 0
A9 PK1 17 11 PB5 5 SCK PB1 1
A10 PK2 18 12 PB6 6 MOSI PB2 2
A11 PK3 19 13 PB7 7 MISO PB3 3
A12 PK4 20 14 PJ1 10
A13 PK5 21 15 PJ0 9
A14 PK6 22 0 PE0 8 - this one is a little odd. *
A15 PK7 23
</pre>
The library supports all interrupt pins, even though not all pins to the
ATmega-2560 processor are exposed on the Arduino board. These pins are
supported as "fake pins", and begin with pin 70 (there are 70 pins on the
ATmega 2560 board). The fake pins are as follows:
<pre>
pin: fake70 PJ2 this is Pin Change Interrupt PCINT11
pin: fake71 PJ3 this is Pin Change Interrupt PCINT12
pin: fake72 PJ4 this is Pin Change Interrupt PCINT13
pin: fake73 PJ5 this is Pin Change Interrupt PCINT14
pin: fake74 PJ6 this is Pin Change Interrupt PCINT15
pin: fake75 PE6 this is External Interrupt INT6
pin: fake76 PE7 this is External Interrupt INT7
</pre>
* Note: Arduino Pin 0 is PE0 (PCINT8), which is RX0. Also, it is the only other
pin on another port on PCI1. This would make it very costly to integrate with
the library's code and thus is not supported by this library. It is the same
pin the Arduino uses to upload sketches, and it is connected to the FT232RL
USB-to-Serial chip (ATmega16U2 on the R3).
### ATmega2561/1281 (MegaCore) Support
<pre>
External Interrupts ------------------------------------------------------------
The following External Interrupts are available on the Arduino/MegaCore:
MegaCore
Pin PORT INT ATmega2561/1281 pin
18 PD0 0 25
19 PD1 1 26
20 PD2 2 27
21 PD3 3 28
4 PE4 4 6
5 PE5 5 7
6 PE6 6 8
7 PE7 7 9
Pin Change Interrupts ----------------------------------------------------------
ATMEGA2561/1281 (MegaCore) Pin Change Interrupts
MegaCore
Pin PORT PCINT
8/SS PB0 0
9/SCK PB1 1
10/MOSI PB2 2
11/MISO PB3 3
12 PB4 4
13 PB5 5
14 PB6 6
15 PB7 7
0 PE0 8 - this one is a little odd. *
</pre>
* Note: Arduino Pin 0 is PE0 (PCINT8), which is RX0. Also, it is the only other
pin on another port on PCI1. This would make it very costly to integrate with
the library's code and thus is not supported by this library. It is the same
pin the Arduino uses to upload sketches, and it is connected to the FT232RL
USB-to-Serial chip (ATmega16U2 on the R3).
### Mighty 1284, Bobuino, EnviroDIY Mayfly, Sodaq Mbili Support
The ATmega 1284p shares pinout with the 644; the only difference is in memory
size. We use the "Mighty 1284" platform as our model, because the needed files are
mature and complete.
<pre>
Interrupt Pins:
Mighty External Mighty Mighty
Pin Interrupt Pin* PORT PCINT ATmega644/1284 pin Pin* PORT PCINT ATmega644/1284 pin
Port 0 PB0 8 1 15 PD7 31 21
2 INT2 PB2 1 PB1 9 2 16 PC0 16 22
10 INT1 PD2 2 PB2 2 3 17 PC1 17 23
11 INT0 PD3 3 PB3 11 4 18 PC2 18 24
4 PB4 12 5 19 PC3 19 25
5 PB5 13 6 20 PC4 20 26
6 PB6 14 7 21 PC5 21 27
7 PB7 15 8 22 PC6 22 28
8 PD0 24 14 23 PC7 23 29
9 PD1 25 15 31/A7 PA7 7 33
10 PD2 26 16 30/A6 PA6 6 34
11 PD3 27 17 29/A5 PA5 5 35
12 PD4 28 18 28/A4 PA4 4 36
13 PD5 29 19 27/A3 PA3 3 37
14 PD6 30 20 26/A2 PA2 2 38
25/A1 PA1 1 39
24/A0 PA0 0 40
Bobuino External Bobuino Bobuino
Pin Interrupt Pin* PORT PCINT ATmega644/1284 pin Pin* PORT PCINT ATmega644/1284 pin
Port 4 PB0 8 1 31 PD7 31 21
2 INT2 PB2 5 PB1 9 2 22 PC0 16 22
10 INT1 PD2 6 PB2 2 3 23 PC1 17 23
11 INT0 PD3 7 PB3 11 4 24 PC2 18 24
10 PB4 12 5 25 PC3 19 25
11 PB5 13 6 26 PC4 20 26
12 PB6 14 7 27 PC5 21 27
13 PB7 15 8 28 PC6 22 28
0 PD0 24 14 29 PC7 23 29
1 PD1 25 15 14/A0 PA7 7 33
2 PD2 26 16 15/A1 PA6 6 34
3 PD3 27 17 16/A2 PA5 5 35
30 PD4 28 18 17/A3 PA4 4 36
8 PD5 29 19 18/A4 PA3 3 37
9 PD6 30 20 19/A5 PA2 2 38
20/A6 PA1 1 39
21/A7 PA0 0 40
Mayfly Mayfly Mayfly
Mbili External Mbili Mbili
Pin Interrupt Pin* PORT PCINT ATmega644/1284 pin Pin* PORT PCINT ATmega644/1284 pin
Port 8 PB0 8 1 7 PD7 31 21
2 INT2 PB2 9 PB1 9 2 16 PC0 16 22
10 INT1 PD2 10 PB2 2 3 17 PC1 17 23
11 INT0 PD3 11 PB3 11 4 18 PC2 18 24
12 PB4 12 5 19 PC3 19 25
13 PB5 13 6 20 PC4 20 26
14 PB6 14 7 21 PC5 21 27
15 PB7 15 8 22 PC6 22 28
0 PD0 24 14 23 PC7 23 29
1 PD1 25 15 31/A7 PA7 7 33
2 PD2 26 16 30/A6 PA6 6 34
3 PD3 27 17 29/A5 PA5 5 35
4 PD4 28 18 28/A4 PA4 4 36
5 PD5 29 19 27/A3 PA3 3 37
6 PD6 30 20 26/A2 PA2 2 38
25/A1 PA1 1 39
24/A0 PA0 0 40
</pre>
</pre>
# Thanks!
Thank you for downloading and enjoying the EnableInterrupt library.
I hope you find it useful. Heck, I wrote it for you- yeah, that's right- you.
The Maker and/or Geek sitting before your project and trying to make little
computers do fun stuff. It's not easy, and my hat goes off to you. I hope I've
made stuff a little easier for you.
This software would not be nearly as useful as it is
without the help of the following people:
Thanks to Loranzo Cafaro for his switch debounce example, to Jevon Wild for his changes to make the
library more functional with PlatformIO (http://docs.platformio.org/en/latest/what-is-platformio.html),
Ricardo JL Rufino for some PlatformIO fixes to the library.json file, and Sara Damiano for
adding support for the Sodaq Mbili and EnviroDIY Mayfly.
And, from the past, this library's predecessor was the PinChangeInt library.
I have done a complete rewrite and not used any of its code, but I learned
a lot by doing the previous one and I feel like I still owe a debt of gratitude
to all the geeks who created/contributed/helped/debugged. So without further
ado, I present the "ACKNOWLEDGEMENTS" section from the previous library. Note
that "this" library in the following refers to PinChangeInt:
> This library was originally written by Chris J. Kiick, Robot builder and all
around geek, who said of it,
> "Hi, Yeah, I wrote the original PCint library. It was a bit of a hack
and the new one has better features. I intended the code to be freely
usable. Didn't really think about a license. Feel free to use it in
your code: I hereby grant you permission."
> Thanks, Chris! A hack? I dare say not, if I have taken this any further it's
merely by standing on the shoulders of giants. This library was the best
"tutorial" I found on Arduino Pin Change Interrupts and because of that I
decided to continue to maintain and (hopefully) improve it. We, the Arduino
community of robot builders and geeks, owe you a great debt of gratitude for
your hack- a hack in the finest sense.
> The library was then picked up by Lex Talionis, who created the Google Code
website. We all owe a debt of thanks to Lex, too, for all his hard work! He is
currently the other official maintainer of this code.
> Many thanks to all the contributors who have contributed bug fixes, code, and
suggestions to this project:
> John Boiles and Baziki (who added fixes to PcInt), Maurice Beelen, nms277,
Akesson Karlpetter, and Orly Andico for various fixes to this code, Rob Tillaart
for some excellent code reviews and nice optimizations, Andre' Franken for a
good bug report that kept me thinking, cserveny.tamas a special shout out for
providing the MEGA code to PinChangeInt, and Pat O'Brien for testing and
reporting on the Arduino Yun.- Thanks!
> A HUGE thanks to JRHelbert for fixing the PJ0 and PJ1 interrupt PCMSK1 issue on
the Mega... 06/2014
> A HUGE thanks to Jan Baeyens ("jantje"), who has graciously DONATED an Arduino
Mega ADK to the PinChangeInt project!!! Wow, thanks Jan! This makes the
2560-based Arduino Mega a first class supported platform- I will be able to test
it and verify that it works.
- In 2018, Alex Reinert contributed Bobuino support. Thanks, Alex!
- In 4/2019 Kizmit99 contributed support for the ATmega2561 and 1281 chips, with
pinouts defined from the MCUdude/MegaCore project. Thanks, Kizmit99!
- In 8/2019 Greg Bowler helped suss out a documentation bug, and contributed
a patch to make the README.md less confusing. Much appreciated.
> Finally, a shout out to Leonard Bernstein. I was inspired by him
(https://www.youtube.com/watch?feature=player_detailpage&v=R9g3Q-qvtss#t=1160)
from a Ted talk by Itay Talgam. None of the contributors, myself included, has
any interest in making money from this library and so I decided to free up the
code as much as possible for any purpose. ...But! You must give credit where
credit is due (it's not only a nice idea, it's the law- as in, the license
terms)!
> "If you love something, give it away."
I apologize if I have forgotten anyone here. Please let me know if so.

عرض الملف

@@ -0,0 +1,23 @@
- examples/test.sh compiles
- #pragma message in .h file up-to-date?
- Use Arduino IDE, compile "SimpleDueZero"
- Tests:
- Simple
- HiSpeed
- HiSpeedAllPins328
- AllPins328
- HiSpeedAllPins2560
- AllPins2560
- ATtinyBlink
- README.md up-to-date?
- extras/RELEASE_NOTES consistent with README.md?
- library.properties current?
- library.json current?
- Git Tagged? git tag -a 2.31 -m 'my version 1.4'; git push origin 2.31 OR git push origin --tags
- Zip file created? ~/bin/zipei 0.9.0
- BinTray:
- Upload Zip file
- Update the downloads area
- Git commit
- Push files to GitHub
- Post to Arduino forums

عرض الملف

@@ -0,0 +1,929 @@
// in vim, :set ts=2 sts=2 sw=2 et
// Enable Interrupts
=====================================================================================================
=====================================================================================================
ATmega328 Support
=====================================================================================================
=====================================================================================================
Interrupt pins:
Pin External Pin Pin Change Pin Pin Change
Interrupt Interrupt Interrupt
3 INT1 PD3 0 PCINT16 PD0 A0 PCINT8 PC0
2 INT0 PD2 1 PCINT17 PD1 A1 PCINT9 PC1
2 PCINT18 PD2 A2 PCINT10 PC2
3 PCINT19 PD3 A3 PCINT11 PC3
4 PCINT20 PD4 A4 PCINT12 PC4
5 PCINT21 PD5 A5 PCINT13 PC5
6 PCINT22 PD6
7 PCINT23 PD7
8 PCINT0 PB0
9 PCINT1 PB1
10 PCINT2 PB2
11 PCINT3 PB3
12 PCINT4 PB4
13 PCINT5 PB5
// The External Interrupts are triggered by the INT0 and INT1 pins or any of the PCINT23...0 pins.
// PIN CHANGE INTERRUPT REGISTER BESTIARY
// ATmega328p and similar (328, 168)
The pin change interrupt PCI2 will trigger if any enabled PCINT[23:16] pin toggles.
The pin change interrupt PCI1 will trigger if any enabled PCINT[14:8] pin toggles.
The pin change interrupt PCI0 will trigger if any enabled PCINT[7:0] pin toggles.
The PCMSK2, PCMSK1 and PCMSK0 Registers control which pins contribute to the pin change interrupts.
Pin change interrupts on PCINT23...0 are detected asynchronously. This implies that these interrupts
can be used for waking the part also from sleep modes other than Idle mode.
// GLOBALLY
SREG: 7 6 5 4 3 2 1 0 (AVR Status Register)
I -Global Interrupt Enable bit Set to enable interrupts.
rw
// PIN CHANGE INTERRUPTS REGISTER BESTIARY
PCICR: 7 6 5 4 3 2 1 0 (When PCIE2 is set and GIE is set, PCI2 is enabled)
PCIE2 1 0 Likewise for 1 and 0.
- - - - - rw rw rw
PCMSK2:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
PCINT23 ... PCINT16 If PCIE2 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0 =PORTD
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT14:8
- PCINT14 ... PCINT8 If PCIE1 in PCICR and this bit is set, it is enabled on that
r rw rw rw rw rw rw rw pin.)
PC6 PC5 PC4 PC3 PC2 PC1 PC0 =PORTC
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
// set...
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, bececomes set. Cleared when
PCIF2 1 0 IRQ is executed. PCIF2 == PCIE2, etc.)
- - - - - rw rw rw
// EXTERNAL INTERRUPTS REGISTER BESTIARY
For ATmega328p and the like.
INT0=pin2, INT1=pin3
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
ISC 11 10 01 00 Interrupt Sense Control Bits
- - - - rw rw rw rw
ISC11 / ISC10 : INT1 ISC01 / ISC00
0 0 Low (similar to ISC11/10)
0 1 Change
1 0 Falling
1 1 Rising
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
INT1 INT0
- - - - - - rw rw set to 1 to enable this interrupt
// set...
EIFR: INTF1: Bit 1: set when edge/logic chg on INT1 triggers IRQ. Cleared when IRQ executed.
INTF0: Bit 0: set when edge/logic chg on INT0 triggers IRQ. Cleared when IRQ executed.
The INT0 and INT1 interrupts can be triggered by a falling or rising edge or a low level. This is
set up as indicated in the specification for the External Interrupt Control Register A EICRA.
When the INT0 or INT1 interrupts are enabled and are configured as level triggered, the inter-
rupts will trigger as long as the pin is held low.
Low level interrupt on INT0 and INT1 is detected asynchronously. This implies that this interrupt
can be used for waking the part also from sleep modes other than Idle mode. The I/O clock is halted
in all sleep modes except Idle mode.
=============================================================================================
Fri Jan 23 21:51:01 CST 2015
PROBLEM:
I have a "dirty" switch: it bounces a lot when pressed. The bounces can occur on the order of
microseconds apart. So pretend I have turned on a port as an input port, and the pullup resistor
is on. I have enabled a Pin Change Interrupt on the pin. It will trigger on any level change.
So when I press the switch, the signal goes from high to low and the interrupt is triggered.
Notice that for Pin Change Interrupts, the interrupt can take place when any pin on the port is
interrupted. If you have the luxury of knowing ahead of time which pin(s) are interrupting, you
can design fast, custom code that will react to your simple situation. But remember that I am
writing a library: I don't know which pin may be doing the interrupting. So I have to survey the
pins to figure out which one(s) changed, and had triggered the interrupt. Furthermore, there is
an appreciable amount of time that it takes from the moment the triggering event happened to
when I enter the interrupt subroutine (ISR) and have gone through the logic to figure out which
pins did the triggering. ...How much time? That I aim to find out.
Why is this a big deal? Remember my bouncy switch? ...The interrupt triggers, the ISR starts up,
and the first thing I need to do is query the port to see the state of its pins. Well, some time
has elapsed since the triggering event and this query. In the course of that time, it's entirely
possible- and I'm writing this because it's not only possible, but it can happen quite readily-
that the state of the pin changes before I get a chance to sample it. So I get an interrupt but
it looks like a false alarm! The ISR never calls the user's function because none of the user's
interrupt pins appear to have changed.
There is no complete solution to this problem, because of the nature of Pin Change Interrupts.
All you can do is mitigate the situation. I will attempt to do so by capturing the state of the
port as early as possible in the ISR. The question is, how early is that?
I attempt a test: my ISR looks like this; this will turn on and off the Arduino Uno's pin 13 LED:
ISR(PORTC_VECT, ISR_NAKED) {
uint8_t interruptMask;
uint8_t ledon, ledoff;
ledon=0b00100000; ledoff=0b0;
PORTB=ledoff; // LOW
PORTB=ledon; // HIGH
PORTB=ledoff; // LOW
PORTB=ledon; // HIGH
PORTB=ledoff; // LOW
(...)
}
The generated assembly code looks like this:
00000292 <__vector_4>:
ledon=0b00100000; ledoff=0b0;
PORTB=ledoff; // LOW
292: 15 b8 out 0x05, r1 ; 5
PORTB=ledon; // HIGH
294: 80 e2 ldi r24, 0x20 ; 32
296: 85 b9 out 0x05, r24 ; 5
PORTB=ledoff; // LOW
298: 15 b8 out 0x05, r1 ; 5
PORTB=ledon; // HIGH
29a: 85 b9 out 0x05, r24 ; 5
PORTB=ledoff; // LOW
29c: 15 b8 out 0x05, r1 ; 5
Notice a little optimization here: r1 is defined to always contain 0, so we don't even have to load
a value from memory. 0 is an important number! This makes the initial command very quick, and by using
an oscilloscope we can see just how quickly the chip reacts after receiving the signal.
see just how fast
***** MACRO vs. INLINE the ISR frontend **************************
The code compiles to very similar assembler. However, the inline is better looking C code.
Refer to the "testing0" branch for comparison.
I will use the INLINE method in the production code.
***** MACRO vs. INLINE the ISR frontend **************************
A lot of the basic Pin and Port definitions are in /usr/avr/include/avr/iom328p.h
================== ================== ================== ================== ==================
=====================================================================================================
=====================================================================================================
Leonardo Support LEONARDO
=====================================================================================================
=====================================================================================================
// Map SPI port to 'new' pins D14..D17
static const uint8_t SS = 17;
static const uint8_t MOSI = 16;
static const uint8_t MISO = 14;
static const uint8_t SCK = 15;
// A0 starts at 18
Interrupt pins:
Pin External Pin Pin Change
Interrupt Interrupt
3 INT0 PD0 8 PCINT4 PB4
2 INT1 PD1 9 PCINT5 PB5
0 INT2 PD2 10 PCINT6 PB6
1 INT3 PD3 11 PCINT7 PB7
7 INT6 PE6 SCK/15 PCINT1 PB1
MOSI/16 PCINT2 PB2
MISO/14 PCINT3 PB3
SS/17 PCINT0 PB0 (on 3rd party boards)
on ICSP:
SCK/15: PCINT1 (PB1)
MOSI/16: PCINT2 (PB2)
MISO/14: PCINT3 (PB3)
PCINT0 (PB0) is RXLED and is not exposed as a pin on the Leonardo board.
External Interrupts ------------------------------------------------------------------------------
...it is recommended to first disable INTn by clearing its Interrupt Enable bit in the
EIMSK Register. Then, the ISCn bit can be changed. Finally, the INTn interrupt flag should be
cleared by writing a logical one to its Interrupt Flag bit (INTFn) in the EIFR Register before the
interrupt is re-enabled.
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
ISC: 31 30 21 20 11 10 01 00 Interrupt Sense Control Bits
rw rw rw rw rw rw rw rw
EICRB: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
ISC: - - 61 60 - - - - Interrupt Sense Control Bits
rw rw rw rw rw rw rw rw
ISCx1 / ISCx0 : INTx
0 0 Low
0 1 Change
1 0 Falling
1 1 Rising
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
n n n n n
- rw - - rw rw rw rw set to 1 to enable this interrupt
n= INTn number
External Interrupt Flag Register is set to 1 when a signal generates an IRQ.
Cleared upon entering the ISR. Can be cleared by writing a 1 to it.
EIFR: 7 6 5 4 3 2 1 0 (External Interrupt Flag Register)
n n n n n
- rw - - rw rw rw rw
n= INTn number
Pin Change Interrupts ---------------------------------------------------------------------------
// PIN CHANGE INTERRUPTS REGISTER BESTIARY
PCICR: 7 6 5 4 3 2 1 0 (When PCIE0 is set and GIE is set, PCI0 is enabled)
PCIE0
- - - - - - - rw
// set...
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, bececomes set. Cleared when
PCIF0 IRQ is executed. PCIF0 == PCIE0.)
- - - - - - - rw Can be cleared by writing 1 to it.
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
=====================================================================================================
=====================================================================================================
ATmega2560 Support
=====================================================================================================
=====================================================================================================
External Interrupts ------------------------------------------------------------------------------
The following External Interrupts are available on the Arduino:
Arduino
Pin* PORT INT ATmega2560 pin
21 PD0 0 43
20 PD1 1 44
19 PD2 2 45
18 PD3 3 46
2 PE4 4 6
3 PE5 5 7
n/c PE6 6 8 (fake pin 75)
n/c PE7 7 9 (fake pin 76)
...it is recommended to first disable INTn by clearing its Interrupt Enable bit in the
EIMSK Register. Then, the ISCn bit can be changed. Finally, the INTn interrupt flag should be
cleared by writing a logical one to its Interrupt Flag bit (INTFn) in the EIFR Register before the
interrupt is re-enabled.
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
ISC: 31 30 21 20 11 10 01 00 Interrupt Sense Control Bits
rw rw rw rw rw rw rw rw
EICRB: 7 6 5 4 3 2 1 0 (External Interrupt Control Register B)
ISC: 71 70 61 60 51 50 41 40 Interrupt Sense Control Bits
rw rw rw rw rw rw rw rw NOTE: NO CONNECTION for INT6 and INT7 on ATmega2560**
ISCx1 / ISCx0 : INTx
0 0 Low
0 1 Change
1 0 Falling
1 1 Rising
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
n n n n n n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
rw rw rw rw rw rw rw rw
n= INTn number
External Interrupt Flag Register is set to 1 when a signal generates an IRQ.
Cleared upon entering the ISR. Can be cleared by writing a 1 to it.
EIFR: 7 6 5 4 3 2 1 0 (External Interrupt Flag Register)
n n n n n n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
rw rw rw rw rw rw rw rw
n= INTn number
** But that doesn't mean they wouldn't make an excellent resource for software interrupts! ;-) )
Pin Change Interrupts ---------------------------------------------------------------------------
ATMEGA2560 Pin Change Interrupts
Arduino Arduino Arduino
Pin* PORT PCINT Pin PORT PCINT Pin PORT PCINT
A8 PK0 16 10 PB4 4 SS PB0 0
A9 PK1 17 11 PB5 5 SCK PB1 1
A10 PK2 18 12 PB6 6 MOSI PB2 2
A11 PK3 19 13 PB7 7 MISO PB3 3
A12 PK4 20 14 PJ1 10
A13 PK5 21 15 PJ0 9
A14 PK6 22 0 PE0 8 - this one is a little odd.*
A15 PK7 23
...indeed, the ATmega2560 chip supports many more Pin Change Interrupt pins but
they are unavailable on the Arduino, unless you want to solder teeny tiny wires.
(However, that doesn't mean they wouldn't make an excellent resource for software interrupts! :-) )
* Note: Arduino Pin 0 is PE0 (PCINT8), which is RX0. Also, it is the only other
pin on another port on PCI1. This would make it very costly to integrate with
the library's code and thus is not supported by this library. It is the same
pin the Arduino uses to upload sketches, and it is connected to the FT232RL
USB-to-Serial chip (ATmega16U2 on the R3).
static const uint8_t SS = 53;
static const uint8_t MOSI = 51;
static const uint8_t MISO = 50;
static const uint8_t SCK = 52;
static const uint8_t A8 = 62;
static const uint8_t A9 = 63;
static const uint8_t A10 = 64;
static const uint8_t A11 = 65;
static const uint8_t A12 = 66;
static const uint8_t A13 = 67;
static const uint8_t A14 = 68;
static const uint8_t A15 = 69;
// PIN CHANGE INTERRUPTS REGISTER BESTIARY for the ATmega2560
PCICR: 7 6 5 4 3 2 1 0 (When PCIE2 is set and GIE is set, PCI2 is enabled)
PCIE2 1 0 Likewise for 1 and 0.
- - - - - rw rw rw
// set...
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, bececomes set. Cleared when
PCIF2 1 0 IRQ is executed. PCIF2 == PCIE2, etc.)
- - - - - rw rw rw
PCMSK2:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
PCINT23 ... PCINT16 If PCIE2 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PK7 PK6 PK5 PK4 PK3 PK2 PK1 PK0 =PORTK
+ + + + + + + + + == available on the Arduino board.
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT15:8
PCINT15 ... PCINT8 If PCIE1 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PJ6 PJ5 PJ4 PJ3 PJ2 PJ1 PJ0 PE0 =PORTJ/E Note pin PE0 is the Arduino's RX pin for programming.
+ + +
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled o2560n PCINT7:0
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
+ + + + + + + +
=====================================================================================================
=====================================================================================================
ATmega644 / 1284 Support (MIGHTY1284 used as a reference, NOT Sanguino)
=====================================================================================================
=====================================================================================================
// Sanguino, Mosquino uino bobino bonanafannafofino, me my momino...
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
// Here I use the mighty-1284p pinout from https://maniacbug.wordpress.com/2011/11/27/arduino-on-atmega1284p-4/
+---\/---+
(D 0) PB0 |1 40| PA0 (AI 0 / D24)
(D 1) PB1 |2 39| PA1 (AI 1 / D25)
INT2 (D 2) PB2 |3 38| PA2 (AI 2 / D26)
PWM (D 3) PB3 |4 37| PA3 (AI 3 / D27)
PWM SS (D 4) PB4 |5 36| PA4 (AI 4 / D28)
MOSI (D 5) PB5 |6 35| PA5 (AI 5 / D29)
PWM MISO (D 6) PB6 |7 34| PA6 (AI 6 / D30)
PWM SCK (D 7) PB7 |8 33| PA7 (AI 7 / D31)
RST |9 32| AREF
VCC |10 31| GND
GND |11 30| AVCC
XTAL2 |12 29| PC7 (D 23)
XTAL1 |13 28| PC6 (D 22)
RX0 (D 8) PD0 |14 27| PC5 (D 21) TDI
TX0 (D 9) PD1 |15 26| PC4 (D 20) TDO
INT0 RX1 (D 10) PD2 |16 25| PC3 (D 19) TMS
INT1 TX1 (D 11) PD3 |17 24| PC2 (D 18) TCK
PWM (D 12) PD4 |18 23| PC1 (D 17) SDA
PWM (D 13) PD5 |19 22| PC0 (D 16) SDL
PWM (D 14) PD6 |20 21| PD7 (D 15) PWM
+--------+
External Interrupts ------------------------------------------------------------------------------
The following External Interrupts are available on the Sanguino:
Sanguino
Pin* PORT INT ATmega644/1284 pin
2 PB2 2 3
10 PD2 0 16
11 PD3 1 17
The following Pin Change Interrupts are available on the ATmega1284p:
Mighty Mighty
Pin* PORT PCINT ATmega644/1284 pin Pin* PORT PCINT ATmega644/1284 pin
0 PB0 8 1 15 PD7 31 21
1 PB1 9 2 16 PC0 16 22
2 PB2 2 3 17 PC1 17 23
3 PB3 11 4 18 PC2 18 24
4 PB4 12 5 19 PC3 19 25
5 PB5 13 6 20 PC4 20 26
6 PB6 14 7 21 PC5 21 27
7 PB7 15 8 22 PC6 22 28
8 PD0 24 14 23 PC7 23 29
9 PD1 25 15 31/A7 PA7 7 33
10 PD2 26 16 30/A6 PA6 6 34
11 PD3 27 17 29/A5 PA5 5 35
12 PD4 28 18 28/A4 PA4 4 36
13 PD5 29 19 27/A3 PA3 3 37
14 PD6 30 20 26/A2 PA2 2 38
25/A1 PA1 1 39
24/A0 PA0 0 40
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
ISC: - - 21 20 11 10 01 00 Interrupt Sense Control Bits (ISCxx)
r r rw rw rw rw rw rw
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
- - - - - n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
r r r r r rw rw rw
n= INTn number
EIFR: External Interrupt Flag Register is set to 1 when a signal generates an IRQ.
Cleared upon entering the ISR. Can be cleared by writing a 1 to it.
EIFR: 7 6 5 4 3 2 1 0 (External Interrupt Flag Register)
- - - - - n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
rw r r r rw rw rw rw
n= INTn number
PCICR: 7 6 5 4 3 2 1 0 (When PCIE2 is set and GIE is set, PCI2 is enabled)
PCIE3 2 1 0 Likewise for 1 and 0.
r r r r rw rw rw rw
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, becomes set. Cleared when
PCIF3 2 1 0 IRQ is executed. PCIF2 == PCIE2, etc.)
r r r r rw rw rw rw
0x73
PCMSK3:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
PCINT31 ... PCINT24 If PCIE2 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0 =PORTD
15 14 13 12 11 10 09 08 -->Sanguino Pins, DIP40 package
0x6D
PCMSK2:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
PCINT23 ... PCINT16 If PCIE2 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0 =PORTC
23 22 21 20 19 18 17 16 -->Sanguino Pins, DIP40 package
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT15:8
PCINT15 ... PCINT8 If PCIE1 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
7 6 5 4 3 2 1 0 -->Sanguino Pins, DIP40 package
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled o2560n PCINT7:0
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 =PORTB
24 25 26 27 28 29 30 31 -->Sanguino Pins, DIP40 package
=====================================================================================================
=====================================================================================================
ATtiny 24/44/84 support ATTINY24
=====================================================================================================
=====================================================================================================
Only the 44/84 are supported.
Support for this chip is based on David Mellis' work at https://github.com/damellis/attiny
This is an ATmega that comes in a 14-pin configuration. There are two ports, A and B. PCint pins are
configured on both ports. The following is the pinout, and shows the Arduino pin numbering scheme:
// ATtiny24/44/84 / ARDUINO
//
// +-\/-+
// VCC 1| |14 GND
// (D 10) PB0 2| |13 PA0 (D 0) == AREF
// (D 9) PB1 3| |12 PA1 (D 1)
// PB3 4| |11 PA2 (D 2)
// PWM INT0 (D 8) PB2 5| |10 PA3 (D 3)
// PWM (D 7) PA7 6| |9 PA4 (D 4)
// PWM (D 6) PA6 7| |8 PA5 (D 5) PWM
// +----+
gcc CPU designations are as follows:
__AVR_ATtiny24__ __AVR_ATtiny24A__ __AVR_ATtiny44__ __AVR_ATtiny44A__
__AVR_ATtiny84__ __AVR_ATtiny84A__
The following External Interrupts are available on the ATtiny24/44/84:
Arduino(tiny)
Pin* PORT INT ATtiny44/84 pin
8 PB2 0 5
The following Pin Change Interrupts are available on the ATmega24/44/84:
Arduino(tiny) Arduino(tiny)
Pin* PORT PCINT ATmega24/44/84 pin Pin* PORT PCINT ATmega24/44/84 pin
0 PA0 0 13 5 PA5 5 8
1 PA1 1 12 6 PA6 6 7
2 PA2 2 11 7 PA7 7 6
3 PA3 3 10 8 PB2 10 5
4 PA4 4 9 9 PB1 9 3
10 PB0 8 2
"fake" 11 PB3 11 4
Interrupt registers are different on the Tiny series. Interrupts are set by MCUCR, GIMSK, GIFR, PCMSK0, and PCMSK1.
EXTERNAL INTERRUPTS
-------------------
MCUCR:
ISC: - - - - - - 01 00 Interrupt Sense Control Bits (ISCxx)
rw rw rw rw rw rw rw rw
ISC01 00
INT0 "is activated if the SREG I-flag and the MCUCR mask is set" (but see GIMSK, below).
ISC01 ISC00
0 0 INT0 interrupted on LOW level
1 1 INT0 interrupted on CHANGE
0 0 INT0 interrupted on FALLING
1 1 INT0 interrupted on RISING
GIMSK:
When INT0 == 1 and SREG I-flag set, External Interrupt enabled.
When PCIE1 == 1 and SREG I-flag set, pin change Interrupt PCINT11:8 enabled.
When PCIE0 == 1 and SREG I-flag set, pin change Interrupt PCINT7:0 enabled.
- INT0 PCIE0 - - - -
PCIE1
rw rw rw rw rw rw rw rw
--------------------------------
GIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, becomes set. Cleared when
INTF0 PCIF0 2 1 0 IRQ is executed. INTF0 == INT0, etc.)
- PCIF1 - - - - INT0 is always cleared when INT0 is a LOW interrupt
r rw rw rw r r r r
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT15:8
PCINT11 ... PCINT8 If PCIE1 in GIMSK and this bit is set, it is enabled on that
r r r r rw rw rw rw pin.)
- - - - PB3 PB2 PB1 PB0 =PORTB
- - - - 4 5 3 2 -->ATtiny 24/44/84 Pins, DIP14 package
- - - - 11* 8 9 10 -->Arduino Pins, DIP14 package. * - "Fake" Arduino pin.
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
PCINT7 ... PCINT0 If PCIE0 in GIMSK and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 =PORTA
7 6 5 4 3 2 1 1 -->ATtiny 24/44/84 Pins, DIP14 package
6 7 8 9 10 11 12 13 -->Arduino Pins, DIP14 package. * - "Fake" Arduino pin.
=====================================================================================================
=====================================================================================================
ATtiny 25/45/85 support ATTINY25
=====================================================================================================
=====================================================================================================
Only the ATtiny 45/85 are supported.
Support for this chip is based on David Mellis' work at https://github.com/damellis/attiny
This is an ATmega that comes in an 8-pin configuration. There is a single port, B.
gcc CPU designations are as follows:
__AVR_ATtiny25__ __AVR_ATtiny45__ __AVR_ATtiny85__
The following is the pinout, and shows the Arduino pin numbering scheme:
// ATtiny25/45/85 / ARDUINO
//
// +-\/-+
// (D 5) PB5 1| |8 Vcc
// (D 3) PB3 2| |7 PB2 (D 2) (INT0) (== Gemma B2)
// (D 4) PB4 3| |6 PB1 (D 1) (== Gemma B1)
// GND 4| |5 PB0 (D 0) (== Gemma B0)
// +----+
The following External Interrupts are available on the ATtiny25/45/85:
Arduino(tiny)
Pin* PORT INT ATtiny25/45/85 pin
2 PB2 0 7
The following Pin Change Interrupts are available on the ATmega25/45/85:
Arduino(tiny) Arduino(tiny)
Pin* PORT PCINT ATmega25/45/85 pin Pin* PORT PCINT ATmega25/45/85 pin
0 PB0 0 5 3 PB3 3 2
1 PB1 1 6 4 PB4 4 3
2 PB2 2 7 5 PB5 5 1
Interrupt registers are different on the Tiny series. Interrupts are set by MCUCR, GIMSK, GIFR, PCMSK0, and PCMSK1.
MCUCR:
ISC: - - - - - - 01 00 Interrupt Sense Control Bits (ISCxx)
rw rw rw rw rw rw rw rw
ISC01 00
INT0 "is activated if the SREG I-flag and the MCUCR mask is set" (but see GIMSK, below).
ISC01 ISC00
0 0 INT0 interrupted on LOW level
1 1 INT0 interrupted on CHANGE
0 0 INT0 interrupted on FALLING
1 1 INT0 interrupted on RISING
GIMSK:
When INT0 == 1 and SREG I-flag set, External Interrupt enabled.
When PCIE == 1 and SREG I-flag set, pin change Interrupt PCINT5:0 enabled.
- INT0 - - - - -
PCIE
r rw rw r r r r r
--------------------------------
GIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, becomes set. Cleared when
INT0 IRQ is executed. INT0 == INT0, etc.)
- PCIE - - - - - INT0 is always cleared when INT0 is a LOW interrupt
r rw rw r r r r r
PCMSK :7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
PCINT5 ... PCINT0 If PCIE0 in GIMSK and this bit is set, it is enabled on that
rw rw rw rw rw rw rw rw pin.)
- - PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
1 3 2 7 6 5 -->ATtiny 25/45/85 Pins, DIP8 package
=================================================================================================================
From http://www.atmel.com/Images/doc8468.pdf:
External interrupts can be sensed and registered either synchronously or asynchronously. Synchronous sensing
requires I/O clock whereas asynchronous sensing does not requires I/O clock. This implies that the interrupts
that are detected asynchronously can be used for waking the device from sleep modes other than idle
mode because the I/O clock is halted in all sleep modes except idle mode. The sense configuration for
external interrupts and pin change interrupts for Atmel ATmega2560 is given in Table 2-2. For device
specific sense configuration, please refer to the respective datasheet.
Table 2-2. External interrupts sense configuration.
Program address Interrupt source Sensing
$0002 INT0 Asynchronous (Edges and level)
$0004 INT1 Asynchronous (Edges and level)
$0006 INT2 Asynchronous (Edges and level)
$0008 INT3 Asynchronous (Edges and level)
$000A INT4 Synchronous (Edges and level)
$000C INT5 Synchronous (Edges and level)
$000E INT6 Synchronous (Edges and level)
$0010 INT7 Synchronous (Edges and level)
$0012 PCINT0 Asynchronous
$0014 PCINT1 Asynchronous
$0016 PCINT2 Asynchronous
From Table 2-2, all the pin change interrupts are detected asynchronously.
...
The interrupt execution response for all the enabled AVR interrupts is four/five clock cycles minimum.
This four/five clock cycles depends on the program counter width. If the program counter width is not
more than two bytes, then the interrupt response time will be four clock cycles minimum and if the
program counter width is more than two bytes, then the interrupt response time will be minimum five
clock cycles. These four/five clock cycles include:
1. Two/Three cycles for pushing the Program Counter (PC) value into the stack.
2. One cycle for updating the stack pointer.
3. One cycle for clearing the Global interrupt enable (I) bit.
If an interrupt occurs when the MCU is in sleep mode, the interrupt execution response time is increased
by five clock cycles. This increase comes in addition to the start-up time from the selected sleep mode.
This start up time is the time it will take to start the clock source.
=====================================================================================================
ARDUINO CPU BESTIARY
=====================================================================================================
See /usr/avr/include/avr/io.h for the actual #defines for the different CPUs.
The CPUs are converted to the #defined macros (eg., __AVR_ATmega169__) by the compiler from
the source file "avr-mcus.def". See
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/avr/avr-mcus.def
$ grep mcu /usr/share/arduino/hardware/arduino/boards.txt
uno.build.mcu=atmega328p
atmega328.build.mcu=atmega328p
diecimila.build.mcu=atmega168
nano328.build.mcu=atmega328p
nano.build.mcu=atmega168
mega2560.build.mcu=atmega2560
mega.build.mcu=atmega1280
leonardo.build.mcu=atmega32u4
esplora.build.mcu=atmega32u4
micro.build.mcu=atmega32u4
mini328.build.mcu=atmega328p
mini.build.mcu=atmega168
ethernet.build.mcu=atmega328p
fio.build.mcu=atmega328p
bt328.build.mcu=atmega328p
bt.build.mcu=atmega168
LilyPadUSB.build.mcu=atmega32u4
lilypad328.build.mcu=atmega328p
lilypad.build.mcu=atmega168
pro5v328.build.mcu=atmega328p
pro5v.build.mcu=atmega168
pro328.build.mcu=atmega328p
pro.build.mcu=atmega168
atmega168.build.mcu=atmega168
atmega8.build.mcu=atmega8
robotControl.build.mcu=atmega32u4
robotMotor.build.mcu=atmega32u4
ISR Register handling
Tested the following code to ensure that all registers would be pushed/popped correctly, even
if I was using NAKED_ISR. Note that I did not run code, I merely eyeballed the output to ensure
it was doing what I expected:
volatile uint8_t storage0;
volatile uint8_t storage1;
volatile uint8_t storage2;
volatile uint8_t storage3;
volatile uint8_t storage4;
volatile uint8_t storage5;
volatile uint8_t storage6;
volatile uint8_t storage7;
volatile uint8_t storage8;
volatile uint8_t storage9;
volatile uint8_t storage10;
volatile uint8_t storage11;
volatile uint8_t storage12;
volatile uint8_t storage13;
volatile uint8_t storage14;
volatile uint8_t storage15;
volatile uint8_t storage16;
volatile uint8_t storage17;
volatile uint8_t storage18;
volatile uint8_t storage19;
void test_ISR(uint8_t current) {
uint8_t local0=storage0;
uint8_t local1=storage1;
uint8_t local2=storage2;
uint8_t local3=storage3;
uint8_t local4=storage4;
uint8_t local5=storage5;
uint8_t local6=storage6;
uint8_t local7=storage7;
uint8_t local8=storage8;
uint8_t local9=storage9;
uint8_t local10=storage10;
uint8_t local11=storage11;
uint8_t local12=storage12;
uint8_t local13=storage13;
uint8_t local14=storage14;
uint8_t local15=storage15;
uint8_t local16=storage16;
uint8_t local17=storage17;
uint8_t local18=storage18;
uint8_t local19=storage19;
local0+=current;
local1+=current;
local2+=current;
local3+=current;
local4+=current;
local5+=current;
local6+=current;
local7+=current;
local8+=current;
local9+=current;
local10+=current;
local11+=current;
local12+=current;
local13+=current;
local14+=current;
local15+=current;
local16+=current;
local17+=current;
local18+=current;
local19+=current;
storage0=local0;
storage1=local1;
storage2=local2;
storage3=local3;
storage4=local4;
storage5=local5;
storage6=local6;
storage7=local7;
storage8=local8;
storage9=local9;
storage10=local10;
storage11=local11;
storage12=local12;
storage13=local13;
storage14=local14;
storage15=local15;
storage16=local16;
storage17=local17;
storage18=local18;
storage19=local19;
}
ISR(PORTD_VECT, ISR_NAKED) {
register uint8_t current asm("r18");
EI_ASM_PREFIX(PIND);
test_ISR(current);
EI_ASM_SUFFIX;
}
MISCELLANEOUS:
STORING FUNCTION POINTERS IN PROGMEM:
http://stackoverflow.com/questions/28261595/put-progmem-function-pointer-array-into-another-progmem-array
Calling the function pointers by checking each pin's bitmask individually:
if (interruptMask & _BV(0)) functionPointerB0(); Cycles
8b8: c0 ff sbrs r28, 0 1 if move on, 2 if skip (to 8bc)
8ba: 05 c0 rjmp .+10 2 (move on)
8bc: e0 91 60 02 lds r30, 0x0260 2
8c0: f0 91 61 02 lds r31, 0x0261 2
8c4: 19 95 eicall 4
8c6: (move on) TOTAL: 10 if matches, 3 if not
== 21 cycles till get to last function call,
then 10 cycles to execute it: 31 cycles
If an interrupt on third pin:
2 x 3 (not matched) + 10 == 16, plus
4 x 3 (not matched) = 28 total.
Calling the function pointers referred to in an array, using while loop:
8c6: d0 e0 ldi r29, 0x00 ; 0 this is the "i" variable
while (1) {
if (interruptMask & 0x01) {
8c8: c0 ff sbrs r28, 0 1 if it's not set, 2 if skip
8ca: 0a c0 rjmp .+20 2 (move on to try next bit at 0x8e0)
(*functionPointerArray[i])();
8cc: ed 2f mov r30, r29 1 (it's set, execute the function)
8ce: f0 e0 ldi r31, 0x00 1 ; loads 0
8d0: ee 0f add r30, r30 1
8d2: ff 1f adc r31, r31 1
8d4: e7 57 subi r30, 0x77 1 ; 119
8d6: fd 4f sbci r31, 0xFD 1 ; 253
8d8: 01 90 ld r0, Z+ 1 load from data memory
8da: f0 81 ld r31, Z 1
8dc: e0 2d mov r30, r0 1
8de: 19 95 eicall 4
}
interruptMask=interruptMask >> 1;
8e0: c6 95 lsr r28 1
if (interruptMask == 0) goto exitISR;
8e2: 11 f0 breq .+4 1 if not zero, 2 if zero (jumps out...) ; 0x8e8 <__vector_9+0x86>
i++;
8e4: df 5f subi r29, 0xFF 1 ; 255
8e6: f0 cf rjmp .-32 2 ; 0x8c8 <__vector_9+0x66>
TOTAL: 14 if matches, 9 if not
== 63 cycles to get to last function call,
then 14 cycles to execute it: 77 cycles
If an interrupt on third pin:
2 x 7 (not matched) == 14 + 14 == 28 total.
Then a couple of cycles to get out.
===========================================================================================================
Space Optimizations
===========================================================================================================
Compile Simple.ino, using pin 10, compile for ATmega2560:
Program: 6402 bytes (2.4% Full)
(.text + .data + .bootloader)
Data: 859 bytes (10.5% Full)
(.data + .bss + .noinit)
Compile Simple.ino, using pin 10, define EI_NOTEXTERNAL:
Program: 5328 bytes (2.0% Full)
(.text + .data + .bootloader)
Data: 843 bytes (10.3% Full)
(.data + .bss + .noinit)
Compile Simple.ino, using pin 10, define EI_NOTPORTJ:
Program: 5006 bytes (1.9% Full)
(.text + .data + .bootloader)
Data: 825 bytes (10.1% Full)
(.data + .bss + .noinit)
Compile Simple.ino, using pin 10, define EI_NOTPORTJ EI_NOTPORTK:
Program: 4686 bytes (1.8% Full)
(.text + .data + .bootloader)
Data: 806 bytes (9.8% Full)
(.data + .bss + .noinit)
Compile Simple.ino, using pin 10, define EI_NOTPORTJ EI_NOTPORTK EI_NOTEXTERNAL:
Program: 4674 bytes (1.8% Full)
(.text + .data + .bootloader)
Data: 806 bytes (9.8% Full)
(.data + .bss + .noinit)

عرض الملف

@@ -0,0 +1,48 @@
#include <EnableInterrupt.h>
#ifdef EI_ATTINY24
#define OUTPUTPIN 10 // == B0
#define INTERRUPTEDPIN 9 // == B1
// Modify this at your leisure. But you must be aware of which port it's on (see below).
#elif defined EI_ATTINY25
#define OUTPUTPIN 0 // == B0
#define INTERRUPTEDPIN 1 // == B1
#else
#error Dang, only ATtiny chips supported by this sketch.
#endif
// Connect a LED to Pin 3. It might be different in different ATtiny micro controllers
//const uint8_t outputBitMask = 0x01;
const uint8_t outputBitMask = digital_pin_to_bit_mask_PGM[OUTPUTPIN];
const uint8_t inputBitMask = digital_pin_to_bit_mask_PGM[INTERRUPTEDPIN];
volatile uint16_t endlessCounter=0; // The count will go back to 0 after hitting 65535.
volatile uint8_t interruptState=0;
void interruptFunction() {
if (interruptState) {
interruptState=0;
PORTB &= ~_BV(outputBitMask);
} else {
interruptState=1;
PORTB |= 1 << outputBitMask;
}
}
// the setup routine runs once when you press reset:
void setup() {
DDRB |= outputBitMask; // OUTPUTPIN is set to output
DDRB &= ~inputBitMask; // INPUTPIN is set to input
PORTB |= inputBitMask; // Pull up the resistor
MCUCR &= ~PUD; // ensure Pull Up Disable is off
enableInterrupt(INTERRUPTEDPIN, interruptFunction, CHANGE);
}
// the loop routine runs over and over again forever:
void loop() {
//digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
//delay(1000); // wait for a second
//digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
//delay(1000); // wait for a second
endlessCounter++; // give it something to do
}

عرض الملف

@@ -0,0 +1,19 @@
## Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
ARDUINO_DIR = /home/schwager/bin/arduino-1.8.5
# ISP_PORT = /dev/ttyACM0
#BOARD_TAG = attiny85at8
BOARD_TAG = attiny44at8
ALTERNATE_CORE = tiny
BOARDS_TXT = ~/sketchbook/hardware/arduino-tiny/boards.txt
ARDUINO_CORE_PATH = /home/schwager/sketchbook/hardware/arduino-tiny/cores/tiny
# ARDUINO_VAR_PATH = ~/sketchbook/hardware/arduino-tiny/cores/tiny
#AVR_TOOLS_DIR = /home/schwager/bin/arduino-1.8.4/hardware/tools/avr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
ISP_PROG = usbtiny
F_CPU = 1000000L
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,228 @@
// EnableInterrupt Simple example sketch
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
#include <EnableInterrupt.h>
volatile uint8_t externalInterruptCounter=0;
volatile uint8_t anyInterruptCounter=0;
#ifdef ARDUINO_MEGA
#define PINCOUNT(x) pin ##x ##Count
// Do not use any Serial.print() in interrupt subroutines. Serial.print() uses interrupts,
// and by default interrupts are off in interrupt subroutines. Interrupt routines should also
// be as fast as possible. Here we just increment counters.
#define interruptFunction(x) \
volatile uint8_t PINCOUNT(x); \
void interruptFunction ##x () { \
anyInterruptCounter++; \
PINCOUNT(x)++; \
}
#define interruptExFunction(x) \
volatile uint8_t PINCOUNT(x); \
void interruptExFunction ##x () { \
externalInterruptCounter++; \
anyInterruptCounter++; \
PINCOUNT(x)++; \
}
#define updateOn(x) \
if (PINCOUNT(x) != 0) { \
printIt((char *) #x, PINCOUNT(x)); \
PINCOUNT(x)=0; \
}
#define disablePCInterrupt(x) \
disableInterrupt( x | PINCHANGEINTERRUPT)
#define setupInterrupt(x) \
EI_printPSTR("Add pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x, interruptFunction##x, CHANGE)
#define setupExInterrupt(x) \
EI_printPSTR("Add External pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x, interruptExFunction##x, CHANGE)
interruptFunction(SS);
interruptFunction(SCK);
interruptFunction(MOSI);
interruptFunction(MISO);
interruptFunction(10);
interruptFunction(11);
interruptFunction(12);
interruptFunction(13);
interruptFunction(14);
interruptFunction(15);
interruptFunction(A8);
interruptFunction(A9);
interruptFunction(A10);
interruptFunction(A11);
interruptFunction(A12);
interruptFunction(A13);
interruptFunction(A14);
interruptFunction(A15);
interruptFunction(70); // fake 70, trick to allow software interrupts on Port J. PJ2
interruptFunction(71); // fake 71. PJ3
interruptFunction(72); // fake 72. PJ4
interruptFunction(73); // fake 73. PJ5
interruptFunction(74); // fake 74. PJ6
// External Interrupts
interruptExFunction(21);
interruptExFunction(20);
interruptExFunction(19);
interruptExFunction(18);
interruptExFunction(2);
interruptExFunction(3);
interruptExFunction(75); // fake 75. PE6
interruptExFunction(76); // fake 76. PE7
#else
#error This sketch supports 2560-based Arduinos only.
#endif
void printIt(char *pinNumber, uint8_t count) {
EI_printPSTR("Pin ");
Serial.print(pinNumber);
EI_printPSTR(" was interrupted: ");
Serial.println(count, DEC);
}
// Attach the interrupt in setup()
// NOTE: PORTJ2-6 (aka, "Pin '70', '71', '72', '73', '74'" are turned on as OUTPUT.
// These are not true pins on the Arduino Mega series!
void setup() {
//uint8_t pind, pink;
Serial.begin(115200);
EI_printPSTR("---------------------------------------");
// PINS 0 and 1 NOT USED BECAUSE OF Serial.print()
setupInterrupt(SS);
setupInterrupt(SCK);
setupInterrupt(MOSI);
setupInterrupt(MISO);
setupInterrupt(10);
setupInterrupt(11);
setupInterrupt(12);
setupInterrupt(13);
setupInterrupt(14);
setupInterrupt(15);
setupInterrupt(A8);
setupInterrupt(A9);
setupInterrupt(A10);
setupInterrupt(A11);
setupInterrupt(A12);
setupInterrupt(A13);
setupInterrupt(A14);
setupInterrupt(A15);
////
DDRJ |=0b01111100; // Non-Arduino Port J pins all become output.
PORTJ|=0b01111100; // Turn them all high.
enableInterrupt(70, interruptFunction70, CHANGE);
enableInterrupt(71, interruptFunction71, CHANGE);
enableInterrupt(72, interruptFunction72, CHANGE);
enableInterrupt(73, interruptFunction73, CHANGE);
enableInterrupt(74, interruptFunction74, CHANGE);
// External Interrupts
setupExInterrupt(21);
setupExInterrupt(20);
setupExInterrupt(19);
setupExInterrupt(18);
setupExInterrupt(2);
setupExInterrupt(3);
////
DDRE |=0b11000000; // Non-Arduino Port E pins all become output.
PORTE|=0b11000000; // Turn them all high.
enableInterrupt(75, interruptExFunction75, CHANGE);
enableInterrupt(76, interruptExFunction76, CHANGE);
}
uint8_t otherToggle=1;
uint8_t enabledToggle=1;
uint8_t disableCounter=0;
// In the loop, we just check to see where the interrupt count is at. The value gets updated by the
// interrupt routine.
void loop() {
uint8_t jbits =0b01111110; // PJ2
uint8_t njbits=0b00000001; // PJ2
uint8_t ebits =0b11000000; // PE6/7
uint8_t nebits=0b00111111; // PE6/7
EI_printPSTR("------\r\n");
delay(1000); // Every second,
if (disableCounter & 0x08) {
EI_printPSTR("Toggle 20, 71, 75, A8, 15, MISO...");
delay(1000);
if (enabledToggle==1) {
EI_printPSTR("---OFF---");
disableInterrupt(20);
disableInterrupt(71);
disableInterrupt(75);
disableInterrupt(15);
disableInterrupt(A8);
disableInterrupt(MISO);
enabledToggle=0;
}
else {
EI_printPSTR("***ON***");
setupExInterrupt(20);
setupInterrupt(71);
setupExInterrupt(75);
setupInterrupt(15);
setupInterrupt(A8);
setupInterrupt(MISO);
enabledToggle=1;
}
disableCounter=0;
}
PORTE &= nebits;
PORTJ &= njbits;
// *out &= njbits;
delay(1);
PORTE |= ebits;
PORTJ |= jbits;
// *out |= jbits;
delay(1);
updateOn(SS);
updateOn(SCK);
updateOn(MOSI)
updateOn(MISO);
updateOn(10);
updateOn(11);
updateOn(12);
updateOn(13);
updateOn(14);
updateOn(15);
updateOn(A8);
updateOn(A9);
updateOn(A10);
updateOn(A11);
updateOn(A12);
updateOn(A13);
updateOn(A14);
updateOn(A15);
// External Interrupts
updateOn(2);
updateOn(3);
updateOn(18);
updateOn(19);
updateOn(20);
updateOn(21);
// Fake Arduino Pins
updateOn(70);
updateOn(71);
updateOn(72);
updateOn(73);
updateOn(74);
// External Interrupts
updateOn(75);
updateOn(76);
if (externalInterruptCounter > 0) { EI_printPSTR(" ext: "); Serial.println(externalInterruptCounter); }; \
externalInterruptCounter=0;
disableCounter++;
}

عرض الملف

@@ -0,0 +1,12 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = mega
BOARD_SUB = atmega2560
ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,200 @@
// EnableInterrupt Simple example sketch
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
// This example demonstrates the use of the EnableInterrupt library on all pins.
// The library has only been tested on an Arduino Duemilanove and Mega ADK.
#include <EnableInterrupt.h>
volatile uint8_t externalInterruptCounter=0;
volatile uint8_t anyInterruptCounter=0;
#ifdef ARDUINO_328
#define PINCOUNT(x) pin ##x ##Count
// Do not use any Serial.print() in interrupt subroutines. Serial.print() uses interrupts,
// and by default interrupts are off in interrupt subroutines. Interrupt routines should also
// be as fast as possible. Here we just increment counters.
#define interruptFunction(x) \
volatile uint8_t PINCOUNT(x); \
void interruptFunction ##x () { \
anyInterruptCounter++; \
PINCOUNT(x)++; \
}
#define interruptExFunction(x) \
volatile uint8_t PINCOUNT(x); \
void interruptExFunction ##x () { \
externalInterruptCounter++; \
anyInterruptCounter++; \
PINCOUNT(x)++; \
}
#define updateOn(x) \
if (PINCOUNT(x) != 0) { \
printIt((char *) #x, PINCOUNT(x)); \
if (externalInterruptCounter > 0) { \
EI_printPSTR(" ext: "); Serial.println(externalInterruptCounter); \
externalInterruptCounter=0; \
}; \
PINCOUNT(x)=0; \
}
#define disablePCInterrupt(x) \
disableInterrupt( x | PINCHANGEINTERRUPT)
#define setupPCInterrupt(x) \
EI_printPSTR("Add PinChange pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x | PINCHANGEINTERRUPT, interruptFunction##x, CHANGE)
#define setupInterrupt(x) \
EI_printPSTR("Add pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x, interruptFunction##x, CHANGE)
#define setupExInterrupt(x) \
EI_printPSTR("Add External pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x , interruptExFunction##x, CHANGE)
interruptFunction(2);
interruptExFunction(3);
interruptFunction(4);
interruptFunction(5);
interruptFunction(6);
interruptFunction(7);
interruptFunction(8);
interruptFunction(9);
interruptFunction(10);
interruptFunction(11);
interruptFunction(12);
interruptFunction(13);
interruptFunction(A0);
interruptFunction(A1);
interruptFunction(A2);
interruptFunction(A3);
interruptFunction(A4);
interruptFunction(A5);
volatile uint8_t otherCounter=0;
void otherInterrupt3Function(void) { // Must appear after interruptFunction(3)
pin3Count++;
otherCounter++;
}
#else
#error This sketch supports 328-based Arduinos only.
#endif
void printIt(char *pinNumber, uint8_t count) {
EI_printPSTR(" Pin ");
Serial.print(pinNumber);
EI_printPSTR(" was interrupted: ");
Serial.println(count, DEC);
}
// Attach the interrupt in setup()
// NOTE: PORTJ2-6 (aka, "Pin '70', '71', '72', '73', '74'" are turned on as OUTPUT.
// These are not true pins on the Arduino Mega series!
void setup() {
Serial.begin(115200);
EI_printPSTR("--- START ------------------------------------\r\n");
#ifdef DEBUG
pinMode(PINSIGNAL, OUTPUT);
#endif
// PINS 0 and 1 NOT USED BECAUSE OF Serial.print()
setupPCInterrupt(2); // by default, will be External Interrupt
setupExInterrupt(3);
setupInterrupt(4);
setupInterrupt(5);
setupInterrupt(6);
setupInterrupt(7);
setupInterrupt(8);
setupInterrupt(9);
setupInterrupt(10);
setupInterrupt(11);
setupInterrupt(12);
#ifndef DEBUG
// NOTE: Because the Arduino Duemilanove has an LED to ground and a 1k resistor in series with
// it to the pin, Voltage at the pin should be hovering between 1-3 volts. 'nearly' ground. So
// a wire to ground will not trip an interrupt, even though we have INPUT_PULLUP. A wire to PWR
// will trigger an interrupt. The Uno has a op-amp buffer/driver to the LED, so will not have
// this problem; it will behave like the other pins.
setupInterrupt(13);
#endif
setupInterrupt(A0);
setupInterrupt(A1);
setupInterrupt(A2);
setupInterrupt(A3);
setupInterrupt(A4);
setupInterrupt(A5);
}
uint8_t otherToggle=1;
uint8_t enabledToggle=1;
uint8_t disableCounter=0;
// In the loop, we just check to see where the interrupt count is at. The value gets updated by
// the interrupt routine.
void loop() {
EI_printPSTR("------\r\n");
delay(1000); // Perform the loop every second.
if (disableCounter & 0x08) {
EI_printPSTR("Toggle 2, 3, 8, A0...");
delay(1000);
if (enabledToggle==1) {
disablePCInterrupt(2);
disableInterrupt(3);
disableInterrupt(8);
disableInterrupt(A0);
enabledToggle=0;
}
else {
if (otherToggle == 1) {
EI_printPSTR("3 is now a Pin Change Interrupt.\r\n");
enableInterrupt(3, otherInterrupt3Function, CHANGE); // make sure we can switch functions.
otherToggle=0;
} else {
EI_printPSTR("3 is now an External Interrupt.\r\n");
otherToggle=1;
setupExInterrupt(3);
}
setupPCInterrupt(2);
setupInterrupt(8);
setupInterrupt(A0);
enabledToggle=1;
}
disableCounter=0;
}
updateOn(2);
updateOn(3);
updateOn(4);
updateOn(5);
updateOn(6);
updateOn(7);
updateOn(8);
updateOn(9);
updateOn(10);
updateOn(11);
updateOn(12);
updateOn(13);
updateOn(A0);
updateOn(A1);
updateOn(A2);
updateOn(A3);
updateOn(A4);
updateOn(A5);
EI_printPSTR("Consolidated interrupt count: "); Serial.println(anyInterruptCounter);
if (otherCounter) {
printIt((char *) "OTHER3", otherCounter);
otherCounter=0;
}
externalInterruptCounter=0;
disableCounter++;
}

عرض الملف

@@ -0,0 +1,12 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = pro
BOARD_SUB = 16MHzatmega328
ARDUINO_PORT = /dev/ttyUSB0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,42 @@
/*
* This example shows how to combine the EnableInterrupt
* library with some simple debouncing code for reading
* button presses consistently.
*
* The interrupt is attached to digital input 5 and the
* service routine just toggles the onboard LED status.
*
* Tested on: ATmega328P
*
* Example by Lorenzo Cafaro <lorenzo@ibisco.net>
*
*/
#include <EnableInterrupt.h>
#define BUTTON_PIN 5
#define DEBOUNCE_DELAY 100 // in ms
uint32_t last_interrupt_time = 0;
uint8_t led_status = 0;
void setup() {
pinMode(BUTTON_PIN, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
enableInterrupt(BUTTON_PIN, isr_handler, RISING);
}
void loop() {
// zZz
}
void isr_handler() {
uint32_t interrupt_time = millis();
if (interrupt_time - last_interrupt_time > DEBOUNCE_DELAY) {
led_status = !led_status;
digitalWrite(LED_BUILTIN, led_status);
}
last_interrupt_time = interrupt_time;
}

عرض الملف

@@ -0,0 +1,64 @@
// EnableInterrupt HiSpeed example sketch
// See https://github.com/GreyGnome/EnableInterrupt and the README.md for more information.
// This example demonstrates the use of the EnableInterrupt library on a single pin of your choice.
// It uses the "HiSpeed" mode of the library.
// This has only been tested on an Arduino Duemilanove and Mega ADK.
// It is designed to work with the Arduino Duemilanove/Uno, Arduino Mega2560/ADK, the Arduino
// Leonardo, and the Arduino Due. Please let me know how you fare on the Leonardo or Due.
// To use:
// 1. You must be using a fairly recent version of the Arduino IDE software on your PC/Mac,
// that is, version 1.0.1 or later. Check Help->About Arduino in the IDE.
// 2. Wire a simple switch to an Analog or Digital pin (pin 8 in the example below)
// that supports interrupts. See https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
// Attach the other end to a GND pin. A "single pole single throw momentary contact normally
// open" // pushbutton switch is best for the most interrupting fun.
// See https://www.sparkfun.com/products/97 and https://octopart.com/b3f-1000-omron-3117
// 3. When pressed, the switch will connect the pin to ground ("low", or "0") voltage, and interrupt the
// processor. See http://arduino.cc/en/Tutorial/DigitalPins
// 4. The interrupt is serviced immediately, and the ISR (Interrupt SubRoutine) sets the value of a global
// variable. Open Tools->Serial Monitor in the IDE to see the results of your interrupts.
// 5. Peruse the Examples directory for more elaborate examples.
// 6. Create your own sketch using the EnableInterrupt library!
// Refer to
// https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
#define NEEDFORSPEED
#define INTERRUPT_FLAG_PIN8 myvariable_pin8 // NOTICE: NO semicolon!!!
#include <EnableInterrupt.h>
// Attach the interrupt in setup()
void setup() {
//uint8_t pind, pink;
Serial.begin(115200);
EI_printPSTR("---------------------------------------\r\n");
pinMode(8, INPUT_PULLUP); // Configure the pin as an input, and turn on the pullup resistor.
// See http://arduino.cc/en/Tutorial/DigitalPins
enableInterruptFast(8, CHANGE);
}
// In the loop, we just check to see where the interrupt count is at. The value gets updated by the
// interrupt routine.
void loop() {
EI_printPSTR("---------------------------------------\r\n");
delay(1000); // Every second,
if (myvariable_pin8) {
EI_printPSTR("Pin 8 was interrupted: ");
Serial.print(myvariable_pin8, DEC); // print the interrupt count.
EI_printPSTR(" times so far.\r\n");
myvariable_pin8=0;
}
else {
EI_printPSTR("No interrupts.\r\n");
}
}

عرض الملف

@@ -0,0 +1,14 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = pro
BOARD_SUB = 16MHzatmega328
ARDUINO_PORT = /dev/ttyUSB0
#BOARD_TAG = 2560
#ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,4 @@
Note: This code has not been tested! Caveat Programmer. I will do it asap.
(I have tested the HiSpeed code using the HiSpeedTest sketch, so I'm confident
the library is working properly. Also this sketch compiles.).
-GreyGnome

عرض الملف

@@ -0,0 +1,205 @@
// EnableInterrupt example sketch: Hi Speed Interrupts, ATmega2560/compatible, all pins
// See the Wiki at https://github.com/GreyGnome/EnableInterrupt/wiki
#define NEEDFORSPEED
#define INTERRUPT_FLAG_PINSS iflag_pinSS
#define INTERRUPT_FLAG_PINSCK iflag_pinSCK
#define INTERRUPT_FLAG_PINMOSI iflag_pinMOSI
#define INTERRUPT_FLAG_PINMISO iflag_pinMISO
#define INTERRUPT_FLAG_PIN10 iflag_pin10
#define INTERRUPT_FLAG_PIN11 iflag_pin11
#define INTERRUPT_FLAG_PIN12 iflag_pin12
#define INTERRUPT_FLAG_PIN13 iflag_pin13
#define INTERRUPT_FLAG_PIN14 iflag_pin14
#define INTERRUPT_FLAG_PIN15 iflag_pin15
#define INTERRUPT_FLAG_PINA8 iflag_pinA8
#define INTERRUPT_FLAG_PINA9 iflag_pinA9
#define INTERRUPT_FLAG_PINA10 iflag_pinA10
#define INTERRUPT_FLAG_PINA11 iflag_pinA11
#define INTERRUPT_FLAG_PINA12 iflag_pinA12
#define INTERRUPT_FLAG_PINA13 iflag_pinA13
#define INTERRUPT_FLAG_PINA14 iflag_pinA14
#define INTERRUPT_FLAG_PINA15 iflag_pinA15
#define INTERRUPT_FLAG_PIN70 iflag_pin70
#define INTERRUPT_FLAG_PIN71 iflag_pin71
#define INTERRUPT_FLAG_PIN72 iflag_pin72
#define INTERRUPT_FLAG_PIN73 iflag_pin73
#define INTERRUPT_FLAG_PIN74 iflag_pin74
#define INTERRUPT_FLAG_PIN21 iflag_pin21
#define INTERRUPT_FLAG_PIN20 iflag_pin20
#define INTERRUPT_FLAG_PIN19 iflag_pin19
#define INTERRUPT_FLAG_PIN18 iflag_pin18
#define INTERRUPT_FLAG_PIN2 iflag_pin2
#define INTERRUPT_FLAG_PIN3 iflag_pin3
#define INTERRUPT_FLAG_PIN75 iflag_pin75
#define INTERRUPT_FLAG_PIN76 iflag_pin76
#define INTERRUPT_FLAG_PIN18 iflag_pin18
#define INTERRUPT_FLAG_PIN19 iflag_pin19
#define INTERRUPT_FLAG_PIN20 iflag_pin20
#define INTERRUPT_FLAG_PIN21 iflag_pin21
#include <EnableInterrupt.h>
volatile uint8_t externalInterruptCounter=0;
volatile uint8_t anyInterruptCounter=0;
#ifdef ARDUINO_MEGA
#define PINCOUNT(x) iflag_pin ##x
#define setupInterrupt(x) \
EI_printPSTR("Add pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterruptFast(x, CHANGE)
#define updateOn(x) \
if (PINCOUNT(x) != 0) { \
printIt((char *) #x, PINCOUNT(x)); \
PINCOUNT(x)=0; \
}
#else
#error This sketch supports 2560-based Arduinos only.
#endif
void printIt(char *pinNumber, uint8_t count) {
EI_printPSTR("Pin ");
Serial.print(pinNumber);
EI_printPSTR(" was interrupted: ");
Serial.println(count, DEC);
}
// Attach the interrupt in setup()
// NOTE: PORTJ2-6 (aka, "Pin '70', '71', '72', '73', '74'" are turned on as OUTPUT.
// These are not true pins on the Arduino Mega series!
void setup() {
Serial.begin(115200);
EI_printPSTR("---------------------------------------");
// PINS 0 and 1 NOT USED BECAUSE OF Serial.print()
setupInterrupt(SS);
setupInterrupt(SCK);
setupInterrupt(MOSI);
setupInterrupt(MISO);
setupInterrupt(10);
setupInterrupt(11);
setupInterrupt(12);
setupInterrupt(13);
setupInterrupt(14);
setupInterrupt(15);
setupInterrupt(A8);
setupInterrupt(A9);
setupInterrupt(A10);
setupInterrupt(A11);
setupInterrupt(A12);
setupInterrupt(A13);
setupInterrupt(A14);
setupInterrupt(A15);
////
DDRJ |=0b01111100; // Non-Arduino Port J pins all become output.
PORTJ|=0b01111100; // Turn them all high.
enableInterruptFast(70, CHANGE);
enableInterruptFast(71, CHANGE);
enableInterruptFast(72, CHANGE);
enableInterruptFast(73, CHANGE);
enableInterruptFast(74, CHANGE);
// External Interrupts
setupInterrupt(21);
setupInterrupt(20);
setupInterrupt(19);
setupInterrupt(18);
setupInterrupt(2);
setupInterrupt(3);
////
DDRE |=0b11000000; // Non-Arduino Port E pins all become output.
PORTE|=0b11000000; // Turn them all high.
enableInterruptFast(75, CHANGE);
enableInterruptFast(76, CHANGE);
}
uint8_t otherToggle=1;
uint8_t enabledToggle=1;
uint8_t disableCounter=0;
// In the loop, we just check to see where the interrupt count is at. The value gets updated by the
// interrupt routine.
void loop() {
uint8_t jbits =0b01111110; // PJ2
uint8_t njbits=0b00000001; // PJ2
uint8_t ebits =0b11000000; // PE6/7
uint8_t nebits=0b00111111; // PE6/7
EI_printPSTR("------\r\n");
delay(1000); // Every second,
if (disableCounter & 0x08) {
EI_printPSTR("Toggle 20, 71, 75, A8, 15, MISO...");
delay(1000);
if (enabledToggle==1) {
EI_printPSTR("---OFF---");
disableInterrupt(20);
disableInterrupt(71);
disableInterrupt(75);
disableInterrupt(15);
disableInterrupt(A8);
disableInterrupt(MISO);
enabledToggle=0;
}
else {
EI_printPSTR("***ON***");
setupInterrupt(20);
enableInterruptFast(71, CHANGE);
enableInterruptFast(75, CHANGE);
setupInterrupt(15);
setupInterrupt(A8);
setupInterrupt(MISO);
enabledToggle=1;
}
disableCounter=0;
}
PORTE &= nebits;
PORTJ &= njbits;
// *out &= njbits;
delay(1);
PORTE |= ebits;
PORTJ |= jbits;
// *out |= jbits;
delay(1);
updateOn(SS);
updateOn(SCK);
updateOn(MOSI)
updateOn(MISO);
updateOn(10);
updateOn(11);
updateOn(12);
updateOn(13);
updateOn(14);
updateOn(15);
updateOn(A8);
updateOn(A9);
updateOn(A10);
updateOn(A11);
updateOn(A12);
updateOn(A13);
updateOn(A14);
updateOn(A15);
// External Interrupts
updateOn(2);
updateOn(3);
updateOn(18);
updateOn(19);
updateOn(20);
updateOn(21);
// Fake Arduino Pins
updateOn(70);
updateOn(71);
updateOn(72);
updateOn(73);
updateOn(74);
// External Interrupts
updateOn(75);
updateOn(76);
if (externalInterruptCounter > 0) { EI_printPSTR(" ext: "); Serial.println(externalInterruptCounter); }; \
externalInterruptCounter=0;
disableCounter++;
}

عرض الملف

@@ -0,0 +1,13 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = mega
BOARD_SUB = atmega2560
ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,177 @@
// EnableInterrupt Simple example sketch
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
// This example demonstrates the use of the EnableInterrupt library on all pins.
// The library has only been tested on an Arduino Duemilanove and Mega ADK.
#define NEEDFORSPEED
#define INTERRUPT_FLAG_PIN2 iflag_pin2
#define INTERRUPT_FLAG_PIN3 iflag_pin3
#define INTERRUPT_FLAG_PIN4 iflag_pin4
#define INTERRUPT_FLAG_PIN5 iflag_pin5
#define INTERRUPT_FLAG_PIN6 iflag_pin6
#define INTERRUPT_FLAG_PIN7 iflag_pin7
#define INTERRUPT_FLAG_PIN8 iflag_pin8
#define INTERRUPT_FLAG_PIN9 iflag_pin9
#define INTERRUPT_FLAG_PIN10 iflag_pin10
#define INTERRUPT_FLAG_PIN11 iflag_pin11
#define INTERRUPT_FLAG_PIN12 iflag_pin12
#define INTERRUPT_FLAG_PIN13 iflag_pin13
#define INTERRUPT_FLAG_PINA0 iflag_pinA0
#define INTERRUPT_FLAG_PINA1 iflag_pinA1
#define INTERRUPT_FLAG_PINA2 iflag_pinA2
#define INTERRUPT_FLAG_PINA3 iflag_pinA3
#define INTERRUPT_FLAG_PINA4 iflag_pinA4
#define INTERRUPT_FLAG_PINA5 iflag_pinA5
#include <EnableInterrupt.h>
volatile uint8_t anyInterruptCounter=0;
#ifdef ARDUINO_328
#define PINCOUNT(x) iflag_pin ##x
#define updateOn(x) \
if (PINCOUNT(x) != 0) { \
printIt((char *) #x, PINCOUNT(x)); \
PINCOUNT(x)=0; \
}
#define disablePCInterrupt(x) \
disableInterrupt( x | PINCHANGEINTERRUPT)
#define setupPCInterrupt(x) \
EI_printPSTR("Add PinChange pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterruptFast( x | PINCHANGEINTERRUPT, CHANGE)
#define setupInterrupt(x) \
EI_printPSTR("Add pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterruptFast( x, CHANGE)
#define setupExInterrupt(x) \
EI_printPSTR("Add External pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterruptFast( x , CHANGE)
#else
#error This sketch supports 328-based Arduinos only.
#endif
void printIt(char *pinNumber, uint8_t count) {
EI_printPSTR(" Pin ");
Serial.print(pinNumber);
EI_printPSTR(" was interrupted: ");
Serial.println(count, DEC);
}
// Attach the interrupt in setup()
// NOTE: PORTJ2-6 (aka, "Pin '70', '71', '72', '73', '74'" are turned on as OUTPUT.
// These are not true pins on the Arduino Mega series!
void setup() {
Serial.begin(115200);
EI_printPSTR("--- START ------------------------------------\r\n");
#ifdef DEBUG
pinMode(PINSIGNAL, OUTPUT);
#endif
// PINS 0 and 1 NOT USED BECAUSE OF Serial.print()
setupPCInterrupt(2); // by default, would be External Interrupt
setupExInterrupt(3);
setupInterrupt(4);
setupInterrupt(5);
setupInterrupt(6);
setupInterrupt(7);
setupInterrupt(8);
setupInterrupt(9);
setupInterrupt(10);
setupInterrupt(11);
setupInterrupt(12);
#ifndef DEBUG
// NOTE: Because the Arduino Duemilanove has an LED to ground and a 1k resistor in series with
// it to the pin, Voltage at the pin should be hovering between 1-3 volts. 'nearly' ground. So
// a wire to ground will not trip an interrupt, even though we have INPUT_PULLUP. A wire to PWR
// will trigger an interrupt. The Uno has a op-amp buffer/driver to the LED, so will not have
// this problem; it will behave like the other pins.
setupInterrupt(13);
#endif
setupInterrupt(A0);
setupInterrupt(A1);
setupInterrupt(A2);
setupInterrupt(A3);
setupInterrupt(A4);
setupInterrupt(A5);
}
uint8_t externalFlag=1;
uint8_t enabledToggle=1;
uint8_t disableCounter=0;
// In the loop, we just check to see where the interrupt count is at. The value gets updated by
// the interrupt routine.
void loop() {
EI_printPSTR("------\r\n");
delay(1000); // Perform the loop every second.
if (disableCounter & 0x08) {
EI_printPSTR("Toggle 2, 3, 4, 8, A0...");
delay(1000);
if (enabledToggle==1) {
EI_printPSTR(" off\r\n");
disablePCInterrupt(2);
if (externalFlag == 1) {
EI_printPSTR("Disable pin 3 external interrupt\r\n");
disableInterrupt(3);
}
else {
EI_printPSTR("Disable pin 3 pin change interrupt\r\n");
disablePCInterrupt(3);
}
disableInterrupt(4);
disableInterrupt(8);
disableInterrupt(A0);
enabledToggle=0;
}
else {
if (externalFlag == 1) {
EI_printPSTR("3 is now a Pin Change Interrupt.\r\n");
setupPCInterrupt(3); // make sure we can switch functions.
externalFlag=0;
} else {
EI_printPSTR("3 is now an External Interrupt.\r\n");
setupExInterrupt(3);
externalFlag=1;
}
setupPCInterrupt(2);
setupInterrupt(4);
setupInterrupt(8);
setupInterrupt(A0);
enabledToggle=1;
}
disableCounter=0;
}
updateOn(2);
updateOn(3);
updateOn(4);
updateOn(5);
updateOn(6);
updateOn(7);
updateOn(8);
updateOn(9);
updateOn(10);
updateOn(11);
updateOn(12);
updateOn(13);
updateOn(A0);
updateOn(A1);
updateOn(A2);
updateOn(A3);
updateOn(A4);
updateOn(A5);
disableCounter++;
}

عرض الملف

@@ -0,0 +1,14 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = pro
BOARD_SUB = 16MHzatmega328
ARDUINO_PORT = /dev/ttyUSB0
#BOARD_TAG = 2560
#ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,103 @@
// EnableInterrupt Simple example sketch
// See https://github.com/GreyGnome/EnableInterrupt and the README.md for more information.
//
// https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
//#define OLDLIBRARY
#define NEEDFORSPEED
#define USEINTERRUPTPIN8 // PORTB
// Define the above, and undefine this for External Interrupt measurements.
//#define USEINTERRUPTPIN2
#if defined USEINTERRUPTPIN8
#define PININTERRUPT 8
#define PININTERRUPT_ON PORTB |= (1 << PB0)
#define PININTERRUPT_OFF PORTB &= ~(1 << PB0)
#define THEINTERRUPTVARIABLE myvariable_pin8
//#define EI_NOTPORTD // will not produce __vector_5 code
#ifdef NEEDFORSPEED
#define INTERRUPT_FLAG_PIN8 myvariable_pin8 // NOTICE: NO semicolon!!! This needs to track the PININTERRUPT pin
#else
#define EI_NOTPORTB
volatile uint8_t myvariable_pin8=0;
#endif
#endif
#if defined USEINTERRUPTPIN2 // PORTD
#define PININTERRUPT 2
#define PININTERRUPT_ON PORTD |= (1 << PD2)
#define PININTERRUPT_OFF PORTD &= ~(1 << PD2)
#define THEINTERRUPTVARIABLE myvariable_pin2
#ifdef NEEDFORSPEED
#define INTERRUPT_FLAG_PIN2 myvariable_pin2 // NOTICE: NO semicolon!!! This needs to track the PININTERRUPT pin
#else
volatile uint8_t myvariable_pin2=0;
#endif
#endif
#ifdef OLDLIBRARY
#include <PinChangeInt.h>
#define EI_printPSTR(x) SerialPrint_P(PSTR(x))
void SerialPrint_P(const char *str) {
for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.write(c);
}
#else
#include <EnableInterrupt.h>
#endif
#include <avr/cpufunc.h>
void incrementMyVariable() { // This isn't used or compiled if NEEDFORSPEED is defined.
THEINTERRUPTVARIABLE++;
}
// Attach the interrupt in setup()
void setup() {
//uint8_t pind, pink;
Serial.begin(115200);
EI_printPSTR("---------------------------------------\r\n");
pinMode(PININTERRUPT, OUTPUT); // Configure the pin as an output
PININTERRUPT_OFF;
#ifdef OLDLIBRARY
attachPinChangeInterrupt(PININTERRUPT, incrementMyVariable, CHANGE);
#else
#ifdef NEEDFORSPEED
enableInterruptFast(PININTERRUPT, CHANGE);
#else
enableInterrupt(PININTERRUPT, incrementMyVariable, CHANGE);
#endif
#endif
EI_printPSTR("Interrupt enabled, let's go!\r\n");
EI_printPSTR("Make sure nothing is connected to pin ");
Serial.println(PININTERRUPT, DEC);
EI_printPSTR("This sketch sends a software interrupt to that pin.\r\n");
}
// In the loop, we just check to see where the interrupt count is at. The value gets updated by the
// interrupt routine.
void loop() {
EI_printPSTR("---------------------------------------\r\n");
delay(1000); // Every second,
PININTERRUPT_ON; // software interrupt
_NOP(); // See "8-bit AVR Microcontroller with 4/8/16/32K Bytes In-System Programmable
_NOP(); // Flash" document, Rev. 8271C-AVR-08/10, p. 71.
_NOP(); // The interrupt signal must be held until PCIFR is changed, in order for the
#if defined USEINTERRUPTPIN8
_NOP(); // CPU to execute the ISR. This requires 4 nop assembler instructions.
#else
// (three nop's for an External Interrupt)
#endif
PININTERRUPT_OFF; // ...This is after the interrupt.
if (THEINTERRUPTVARIABLE > 0) {
EI_printPSTR("Pin was interrupted: ");
Serial.print(THEINTERRUPTVARIABLE, DEC); // print the interrupt count.
EI_printPSTR(" times this iteration.\r\n");
THEINTERRUPTVARIABLE=0;
}
else {
EI_printPSTR("No interrupts.\r\n");
}
}

عرض الملف

@@ -0,0 +1,13 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = atmega328
ARDUINO_PORT = /dev/ttyUSB0
#BOARD_TAG = 2560
#ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,214 @@
// EnableInterrupt example sketch
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
// This example demonstrates the use of the EnableInterrupt library on all pins.
// It tests the EI_ARDUINO_INTERRUPTED_PIN facility.
// The library has only been tested on an Arduino Duemilanove and Mega ADK.
#define EI_ARDUINO_INTERRUPTED_PIN
#include <EnableInterrupt.h>
volatile uint8_t externalInterruptFlag=0;
volatile uint8_t pinChangeInterruptFlag=0;
volatile uint8_t pin70Flag=0;
#ifdef ARDUINO_MEGA
void interruptFunctionPin70 () {
pinChangeInterruptFlag=arduinoInterruptedPin;
pin70Flag++;
}
void interruptFunction () {
pinChangeInterruptFlag=arduinoInterruptedPin;
}
void interruptExFunction () {
externalInterruptFlag=arduinoInterruptedPin;
}
#define disablePCInterrupt(x) \
disableInterrupt( x | PINCHANGEINTERRUPT)
#define setupPCInterrupt(x) \
EI_printPSTR("Add PinChange pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x | PINCHANGEINTERRUPT, interruptFunction, CHANGE)
#define setupInterrupt(x) \
EI_printPSTR("Add pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x, interruptFunction, CHANGE)
#define setupExInterrupt(x) \
EI_printPSTR("Add External pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x , interruptExFunction, CHANGE)
#else
#error This sketch supports 328-based Arduinos only.
#endif
void printIt(char *pinNumber, uint8_t count) {
EI_printPSTR(" Pin ");
Serial.print(pinNumber);
EI_printPSTR(" was interrupted: ");
Serial.println(count, DEC);
}
#define PIN70_PORTBITMAP 0b00000100
#define PIN71_PORTBITMAP 0b00001000
#define PIN72_PORTBITMAP 0b00010000
#define PIN73_PORTBITMAP 0b00100000
#define PIN74_PORTBITMAP 0b01000000
#define PIN75_PORTBITMAP 0b01000000
#define PIN76_PORTBITMAP 0b10000000
// Attach the interrupt in setup()
// NOTE: PORTJ2-6 (aka, "Pin '70', '71', '72', '73', '74'" are turned on as OUTPUT.
// These are not true pins on the Arduino Mega series!
void setup() {
Serial.begin(115200);
EI_printPSTR("--- START ------------------------------------\r\n");
setupInterrupt(SS);
setupInterrupt(SCK);
setupInterrupt(MOSI);
setupInterrupt(MISO);
setupInterrupt(10);
setupInterrupt(11);
setupInterrupt(12);
setupInterrupt(13);
setupInterrupt(14);
setupInterrupt(15);
setupInterrupt(A8);
setupInterrupt(A9);
setupInterrupt(A10);
setupInterrupt(A11);
setupInterrupt(A12);
setupInterrupt(A13);
setupInterrupt(A14);
setupInterrupt(A15);
//// 0b01111100
// MIKE- Why turn them all high? I think they should be 0!
DDRJ |= PIN70_PORTBITMAP | PIN71_PORTBITMAP | PIN72_PORTBITMAP
| PIN73_PORTBITMAP | PIN74_PORTBITMAP ; // Non-Arduino Port J pins all become output.
PORTJ &= ~(PIN70_PORTBITMAP | PIN71_PORTBITMAP | PIN72_PORTBITMAP
| PIN73_PORTBITMAP | PIN74_PORTBITMAP) ; // Turn them all low.
//// 0b11000000
DDRE |= PIN75_PORTBITMAP | PIN76_PORTBITMAP; // Non-Arduino Port E pins all become output.
PORTE &= ~(PIN75_PORTBITMAP | PIN76_PORTBITMAP); // Turn them all low.
// MIKE- replace this if necessary: enableInterrupt(70, interruptFunctionPin70, CHANGE);
enableInterrupt(70, interruptFunction, CHANGE);
enableInterrupt(71, interruptFunction, CHANGE);
enableInterrupt(72, interruptFunction, CHANGE);
enableInterrupt(73, interruptFunction, CHANGE);
enableInterrupt(74, interruptFunction, CHANGE);
// External Interrupts
setupExInterrupt(21);
setupExInterrupt(20);
setupExInterrupt(19);
setupExInterrupt(18);
setupExInterrupt(2);
setupExInterrupt(3);
enableInterrupt(75, interruptExFunction, CHANGE);
enableInterrupt(76, interruptExFunction, CHANGE);
}
#define IS_PINCHANGE 0
#define IS_EXTERNAL 1
#define FLIP 0
#define FLOP 1
uint8_t pin3state=IS_PINCHANGE;
uint8_t enabledToggle=FLOP;
uint8_t toggleCounter=0;
uint16_t loopCounter=0;
uint8_t portj_follower = PIN70_PORTBITMAP;
uint8_t porte_follower = PIN75_PORTBITMAP;
uint8_t current_pin_state = 0;
// In the loop, we just check to see where the interrupt count is at. The value gets updated by
// the interrupt routine.
void loop() {
/*
if (toggleCounter & 0x80) {
EI_printPSTR("Toggle 20, 71, 75, A8, 15, MISO...");
delay(200);
if (enabledToggle==FLOP) {
disableInterrupt(20);
disableInterrupt(71);
disableInterrupt(75);
disableInterrupt(15);
disableInterrupt(A8);
disableInterrupt(MISO);
enabledToggle=FLIP;
}
else {
EI_printPSTR("***ON***");
setupExInterrupt(20);
setupInterrupt(71);
setupExInterrupt(75);
setupInterrupt(15);
setupInterrupt(A8);
setupInterrupt(MISO);
enabledToggle=FLOP;
}
toggleCounter=0;
}*/
loopCounter++;
// Starting positions:
// portjfollower 00000100 PORTJ 00000000 // Keep track of port j
// portefollower 00000000 PORTE 00000000 // Keep track of port e
// current_pin_state 0 // track the state of the current pin
if (loopCounter == 0x3FFF) {
if (portj_follower <= PIN74_PORTBITMAP) {
EI_printPSTR("Interrupt fake pins...");
// If the pin is on, turn it off, and go to the next pin
if (current_pin_state) {
PORTJ ^= portj_follower; // turn it off
portj_follower <<= 1;
current_pin_state=0;
} else {
// if the pin is off, turn it on
PORTJ ^= portj_follower; // turn it on
current_pin_state=1;
}
delay(1); // run a few instructions after triggering the interrupt.
} else if (porte_follower >= PIN75_PORTBITMAP) {
EI_printPSTR("Interrupt fake pins...");
if (current_pin_state) {
PORTE ^= porte_follower; // turn it off
porte_follower <<= 1;
current_pin_state=0;
} else {
PORTE ^= porte_follower; // turn it on
current_pin_state=1;
}
delay(1); // run a few instructions after triggering the interrupt.
} else {
portj_follower=PIN70_PORTBITMAP;
porte_follower=PIN75_PORTBITMAP;
}
loopCounter=0;
}
if (pinChangeInterruptFlag) {
//EI_printPSTR("Pin Change interrupt, pin "); Serial.println(arduinoInterruptedPin);
EI_printPSTR("pci: "); Serial.println(pinChangeInterruptFlag);
EI_printPSTR(", state: "); Serial.println(arduinoPinState);
arduinoInterruptedPin=0;
pinChangeInterruptFlag=0;
toggleCounter++;
}
if (externalInterruptFlag) {
//EI_printPSTR("External interrupt, pin "); Serial.println(arduinoInterruptedPin);
EI_printPSTR("ext: "); Serial.println(externalInterruptFlag);
EI_printPSTR(", state: "); Serial.println(arduinoPinState);
arduinoInterruptedPin=0;
externalInterruptFlag=0;
toggleCounter++;
}
}

عرض الملف

@@ -0,0 +1,14 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
#BOARD_TAG = atmega328
#ARDUINO_PORT = /dev/ttyUSB0
BOARD_TAG = mega
BOARD_SUB = atmega2560
ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,154 @@
// EnableInterrupt example sketch
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
// This example demonstrates the use of the EnableInterrupt library on all pins.
// It tests the EI_ARDUINO_INTERRUPTED_PIN facility.
// The library has only been tested on an Arduino Duemilanove and Mega ADK.
#define EI_ARDUINO_INTERRUPTED_PIN
#include <EnableInterrupt.h>
volatile uint8_t externalInterruptFlag=0;
volatile uint8_t pinChangeInterruptFlag=0;
volatile uint8_t pinState=0;
#ifdef ARDUINO_328
#define PINCOUNT(x) pin ##x ##Count
void interruptFunction () {
pinChangeInterruptFlag=arduinoInterruptedPin;
pinState=arduinoPinState;
}
void interruptExFunction () {
externalInterruptFlag=arduinoInterruptedPin;
pinState=arduinoPinState;
}
#define disablePCInterrupt(x) \
disableInterrupt( x | PINCHANGEINTERRUPT)
#define setupPCInterrupt(x) \
EI_printPSTR("Add PinChange pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x | PINCHANGEINTERRUPT, interruptFunction, CHANGE)
#define setupInterrupt(x) \
EI_printPSTR("Add pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x, interruptFunction, CHANGE)
#define setupExInterrupt(x) \
EI_printPSTR("Add External pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x , interruptExFunction, CHANGE)
#else
#error This sketch supports 328-based Arduinos only.
#endif
void printIt(char *pinNumber, uint8_t count) {
EI_printPSTR(" Pin ");
Serial.print(pinNumber);
EI_printPSTR(" was interrupted: ");
Serial.println(count, DEC);
}
// Attach the interrupt in setup()
// NOTE: PORTJ2-6 (aka, "Pin '70', '71', '72', '73', '74'" are turned on as OUTPUT.
// These are not true pins on the Arduino Mega series!
void setup() {
Serial.begin(115200);
EI_printPSTR("--- START ------------------------------------\r\n");
#ifdef DEBUG
pinMode(PINSIGNAL, OUTPUT);
#endif
// PINS 0 and 1 NOT USED BECAUSE OF Serial.print()
setupPCInterrupt(2); // by default, would be External Interrupt
setupExInterrupt(3);
setupInterrupt(4);
setupInterrupt(5);
setupInterrupt(6);
setupInterrupt(7);
setupInterrupt(8);
setupInterrupt(9);
setupInterrupt(10);
setupInterrupt(11);
setupInterrupt(12);
#ifndef DEBUG
// NOTE: Because the Arduino Duemilanove has an LED to ground and a 1k resistor in series with
// it to the pin, Voltage at the pin should be hovering between 1-3 volts. 'nearly' ground. So
// a wire to ground will not trip an interrupt, even though we have INPUT_PULLUP. A wire to PWR
// will trigger an interrupt. The Uno has an op-amp buffer/driver to the LED, so will not have
// this problem; it will behave like the other pins.
setupInterrupt(13);
#endif
setupInterrupt(A0);
setupInterrupt(A1);
setupInterrupt(A2);
setupInterrupt(A3);
setupInterrupt(A4);
setupInterrupt(A5);
}
#define IS_PINCHANGE 0
#define IS_EXTERNAL 1
#define FLIP 0
#define FLOP 1
uint8_t pin3state=IS_PINCHANGE;
uint8_t enabledToggle=FLOP;
uint8_t toggleCounter=0;
// In the loop, we just check to see where the interrupt count is at. The value gets updated by
// the interrupt routine.
void loop() {
if (toggleCounter & 0x10) {
EI_printPSTR("Toggle 2, 3, 8, A0...");
delay(200);
if (enabledToggle==FLOP) {
if (pin3state==IS_PINCHANGE)
disablePCInterrupt(3);
else
disableInterrupt(3);
disablePCInterrupt(2);
disableInterrupt(8);
disableInterrupt(A0);
enabledToggle=FLIP;
}
else {
EI_printPSTR("3 is now a");
if (pin3state == IS_PINCHANGE) {
setupExInterrupt(3);
EI_printPSTR("n external interrupt.\r\n");
pin3state=IS_EXTERNAL;
} else {
setupExInterrupt(3);
EI_printPSTR(" pin change interrupt.\r\n");
pin3state=IS_PINCHANGE;
}
setupPCInterrupt(2);
setupInterrupt(8);
setupInterrupt(A0);
enabledToggle=FLOP;
}
toggleCounter=0;
}
// Bug: 0 is not (technically) a proper test because (technically) we have Arduino pin 0.
// But we don't support pin 0 in this sketch (it's used for Serial print).
if (pinChangeInterruptFlag) {
EI_printPSTR("Pin Change interrupt, pin "); Serial.println(pinChangeInterruptFlag);
pinChangeInterruptFlag=0;
EI_printPSTR(", pin state: "); Serial.println(pinState);
toggleCounter++;
}
if (externalInterruptFlag) {
EI_printPSTR("External interrupt, pin "); Serial.println(externalInterruptFlag);
externalInterruptFlag=0;
EI_printPSTR(", pin state: "); Serial.println(pinState);
toggleCounter++;
}
}

عرض الملف

@@ -0,0 +1,14 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = pro
BOARD_SUB = 16MHzatmega328
ARDUINO_PORT = /dev/ttyUSB0
#BOARD_TAG = 2560
#ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,204 @@
// EnableInterrupt Simple example sketch for the ATmega 644/1284 series of chips.
// Note that this sketch is kind of silly, because it uses printf's which depend on
// Arduino's USB-serial converters that don't come with a naked 1284, naturally.
// This sketch is merely to ensure a proper compile.
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
// This example demonstrates the use of the EnableInterrupt library on all pins.
// The library has only been tested on an Arduino Duemilanove and Mega ADK.
#include <EnableInterrupt.h>
volatile uint8_t externalInterruptCounter=0;
volatile uint8_t anyInterruptCounter=0;
#ifdef MIGHTY1284
#define PINCOUNT(x) pin ##x ##Count
// Do not use any Serial.print() in interrupt subroutines. Serial.print() uses interrupts,
// and by default interrupts are off in interrupt subroutines. Interrupt routines should also
// be as fast as possible. Here we just increment counters.
#define interruptFunction(x) \
volatile uint8_t PINCOUNT(x); \
void interruptFunction ##x () { \
anyInterruptCounter++; \
PINCOUNT(x)++; \
}
#define interruptExFunction(x) \
volatile uint8_t PINCOUNT(x); \
void interruptExFunction ##x () { \
externalInterruptCounter++; \
anyInterruptCounter++; \
PINCOUNT(x)++; \
}
#define updateOn(x) \
if (PINCOUNT(x) != 0) { \
printIt((char *) #x, PINCOUNT(x)); \
if (externalInterruptCounter > 0) { \
EI_printPSTR(" ext: "); Serial.println(externalInterruptCounter); \
externalInterruptCounter=0; \
}; \
PINCOUNT(x)=0; \
}
#define disablePCInterrupt(x) \
disableInterrupt( x | PINCHANGEINTERRUPT)
#define setupPCInterrupt(x) \
EI_printPSTR("Add PinChange pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x | PINCHANGEINTERRUPT, interruptFunction##x, CHANGE)
#define setupInterrupt(x) \
EI_printPSTR("Add pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x, interruptFunction##x, CHANGE)
#define setupExInterrupt(x) \
EI_printPSTR("Add External pin: "); \
EI_printPSTR(#x); \
EI_printPSTR("\r\n"); \
pinMode( x, INPUT_PULLUP); \
enableInterrupt( x , interruptExFunction##x, CHANGE)
interruptFunction(2);
interruptExFunction(3);
interruptFunction(4);
interruptFunction(5);
interruptFunction(6);
interruptFunction(7);
interruptFunction(8);
interruptFunction(9);
interruptFunction(10);
interruptFunction(11);
interruptFunction(12);
interruptFunction(13);
interruptFunction(A0);
interruptFunction(A1);
interruptFunction(A2);
interruptFunction(A3);
interruptFunction(A4);
interruptFunction(A5);
volatile uint8_t otherCounter=0;
void otherInterrupt3Function(void) { // Must appear after interruptFunction(3)
pin3Count++;
otherCounter++;
}
#else
#error This sketch supports 1284p-based Arduino-likes only.
#endif
void printIt(char *pinNumber, uint8_t count) {
EI_printPSTR(" Pin ");
Serial.print(pinNumber);
EI_printPSTR(" was interrupted: ");
Serial.println(count, DEC);
}
// Attach the interrupt in setup()
// NOTE: PORTJ2-6 (aka, "Pin '70', '71', '72', '73', '74'" are turned on as OUTPUT.
// These are not true pins on the Arduino Mega series!
void setup() {
Serial.begin(115200);
EI_printPSTR("--- START ------------------------------------\r\n");
#ifdef DEBUG
pinMode(PINSIGNAL, OUTPUT);
#endif
// PINS 0 and 1 NOT USED BECAUSE OF Serial.print()
setupPCInterrupt(2); // by default, will be External Interrupt
setupExInterrupt(3);
setupInterrupt(4);
setupInterrupt(5);
setupInterrupt(6);
setupInterrupt(7);
setupInterrupt(8);
setupInterrupt(9);
setupInterrupt(10);
setupInterrupt(11);
setupInterrupt(12);
#ifndef DEBUG
// NOTE: Because the Arduino Duemilanove has an LED to ground and a 1k resistor in series with
// it to the pin, Voltage at the pin should be hovering between 1-3 volts. 'nearly' ground. So
// a wire to ground will not trip an interrupt, even though we have INPUT_PULLUP. A wire to PWR
// will trigger an interrupt. The Uno has a op-amp buffer/driver to the LED, so will not have
// this problem; it will behave like the other pins.
setupInterrupt(13);
#endif
setupInterrupt(A0);
setupInterrupt(A1);
setupInterrupt(A2);
setupInterrupt(A3);
setupInterrupt(A4);
setupInterrupt(A5);
}
uint8_t otherToggle=1;
uint8_t enabledToggle=1;
uint8_t disableCounter=0;
// In the loop, we just check to see where the interrupt count is at. The value gets updated by
// the interrupt routine.
void loop() {
EI_printPSTR("------\r\n");
delay(1000); // Perform the loop every second.
if (disableCounter & 0x08) {
EI_printPSTR("Toggle 2, 3, 8, A0...");
delay(1000);
if (enabledToggle==1) {
disablePCInterrupt(2);
disableInterrupt(3);
disableInterrupt(8);
disableInterrupt(A0);
enabledToggle=0;
}
else {
if (otherToggle == 1) {
EI_printPSTR("3 is now a Pin Change Interrupt.\r\n");
enableInterrupt(3, otherInterrupt3Function, CHANGE); // make sure we can switch functions.
otherToggle=0;
} else {
EI_printPSTR("3 is now an External Interrupt.\r\n");
otherToggle=1;
setupExInterrupt(3);
}
setupPCInterrupt(2);
setupInterrupt(8);
setupInterrupt(A0);
enabledToggle=1;
}
disableCounter=0;
}
updateOn(2);
updateOn(3);
updateOn(4);
updateOn(5);
updateOn(6);
updateOn(7);
updateOn(8);
updateOn(9);
updateOn(10);
updateOn(11);
updateOn(12);
updateOn(13);
updateOn(A0);
updateOn(A1);
updateOn(A2);
updateOn(A3);
updateOn(A4);
updateOn(A5);
EI_printPSTR("Consolidated interrupt count: "); Serial.println(anyInterruptCounter);
if (otherCounter) {
printIt((char *) "OTHER3", otherCounter);
otherCounter=0;
}
externalInterruptCounter=0;
disableCounter++;
}

عرض الملف

@@ -0,0 +1,14 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = pro
BOARD_SUB = 16MHzatmega328
ARDUINO_PORT = /dev/ttyUSB0
#BOARD_TAG = 2560
#ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,129 @@
// EnableInterrupt OOSimple object-oriented example sketch.
// See https://github.com/GreyGnome/EnableInterrupt and the README.md for more information.
#include <EnableInterrupt.h>
// Modify this at your leisure. See https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
#define ARDUINOPIN 8
class Simple {
public:
Simple() {
init();
}
void updateSimpleVariable();
uint8_t getSimpleVariable();
private:
volatile uint8_t _sv; // a simple variable. Notice that it is volatile.
void init();
};
void Simple::init() {
_sv=0;
}
void Simple::updateSimpleVariable() {
_sv++;
}
uint8_t Simple::getSimpleVariable() {
return _sv;
}
#ifdef __cplusplus
extern "C" {
#endif
void *createSimple() {
return new Simple();
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
uint8_t getSimpleVariable(void *anObject) {
return static_cast<Simple*>(anObject)->getSimpleVariable();
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
void updateSimpleVariable(void *anObject) {
static_cast<Simple*>(anObject)->updateSimpleVariable();
}
#ifdef __cplusplus
}
#endif
void *simpleObject0; // this is numbered 0. You can create more, for example void *simpleObject1
#ifdef __cplusplus
extern "C" {
#endif
// If you create more objects, you need to create more interruptFunctionN()'s
// that update their simple variables, for example interruptFunction1() .
void interruptFunction0() {
updateSimpleVariable(simpleObject0);
}
#ifdef __cplusplus
}
#endif
// Attach the interrupt in setup()
void setup() {
Serial.begin(115200);
Serial.println("---------------------------------------");
// If you want to enable more pins, you will need to recreate these 3 lines for
// your new pin, object, and function.
pinMode(ARDUINOPIN, INPUT_PULLUP); // See http://arduino.cc/en/Tutorial/DigitalPins
simpleObject0 = createSimple();
enableInterrupt(ARDUINOPIN, interruptFunction0, CHANGE);
}
// In the loop, we just print our object's simple variable. It is updated by the interrupt routine.
void loop() {
Serial.println("---------------------------------------");
delay(1000); // Every second,
Serial.print("Pin was interrupted: ");
Serial.print(getSimpleVariable(simpleObject0), DEC); // print the interrupt count.
Serial.println(" times so far.");
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// GORY DETAILS //////////////////////////////////////
// This example demonstrates the use of the EnableInterrupt library on a single pin of your choice.
// It demonstrates calling an object's method from an interrupt. Other objects can be created and called
// by simply and creating more simpleObjectN's adding more interruptFunctionN()'s.
//
// This has only been tested on an Arduino Duemilanove and Mega ADK.
// It is designed to work with the Arduino Duemilanove/Uno, Arduino Mega2560/ADK, the Arduino
// Leonardo, and the Arduino Due. Please let me know how you fare on the Leonardo or Due.
// To use:
// 1. You must be using a fairly recent version of the Arduino IDE software on your PC/Mac,
// that is, version 1.0.1 or later. Check Help->About Arduino in the IDE.
// 2. Wire a simple switch to any Analog or Digital pin (known as ARDUINOPIN, defined below)
// that supports interrupts. See https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
// Attach the other end to a GND pin. A "single pole single throw momentary contact normally
// open" // pushbutton switch is best for the most interrupting fun.
// See https://www.sparkfun.com/products/97 and https://octopart.com/b3f-1000-omron-3117
// 3. When pressed, the switch will connect the pin to ground ("low", or "0") voltage, and interrupt the
// processor. See http://arduino.cc/en/Tutorial/DigitalPins
// 4. The interrupt is serviced immediately, and the ISR (Interrupt SubRoutine) sets the value of a global
// variable. Open Tools->Serial Monitor in the IDE to see the results of your interrupts.
// 5. Peruse the Examples directory for more elaborate examples.
// 6. Create your own sketch using the EnableInterrupt library!

عرض الملف

@@ -0,0 +1,39 @@
## Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
#ARDUINO_DIR = /home/schwager/bin/arduino-1.6.8
ARDUINO_DIR = /home/schwager/bin/arduino-1.8.5
#ARDMK_DIR = /home/schwager/Projects/Arduino/libraries/EnableInterrupt/examples/Simple
ARDMK_DIR = /usr/share/arduino
#AVR_TOOLS_DIR = /home/schwager/bin/arduino-1.6.8/hardware/tools/avr
AVR_TOOLS_DIR = /home/schwager/bin/arduino-1.8.5/hardware/tools/avr
BOARD_TAG = pro
BOARD_SUB = 16MHzatmega328
ARDUINO_PORT = /dev/ttyUSB0
##BOARD_TAG = 2560
##ARDUINO_PORT = /dev/ttyACM0
#ARDUINO_LIBS =
#AVR_TOOLS_DIR = /usr
#
#CFLAGS_STD = -g
#CXXFLAGS_STD = -g
#
#include /usr/share/arduino/Arduino.mk
########################################################################
## Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
#
#ARDUINO_DIR = /home/schwager/bin/arduino-1.6.4
#BOARD_SUB = atmega1284p
#CFLAGS_STD = -g -I /home/schwager/sketchbook/hardware/mighty-1284p-master/variants/standard
#CXXFLAGS_STD = -g -I /home/schwager/sketchbook/hardware/mighty-1284p-master/variants/standard
#
#ISP_PROG = usbasp
# from boards.txt
#BOARD_TAG = mighty_opt
#ALTERNATE_CORE = mighty-1284p-master
# This is set in the boards.txt file.
#F_CPU = 16000000L
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,31 @@
## Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
#BOARD_TAG = atmega328
#ARDUINO_PORT = /dev/ttyUSB0
##BOARD_TAG = 2560
##ARDUINO_PORT = /dev/ttyACM0
#ARDUINO_LIBS =
#AVR_TOOLS_DIR = /usr
#
#CFLAGS_STD = -g
#CXXFLAGS_STD = -g
#
#include /usr/share/arduino/Arduino.mk
########################################################################
## Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
#
ARDUINO_DIR = /home/schwager/bin/arduino-1.8.4
BOARD_SUB = atmega1284p
CFLAGS_STD = -g -I /home/schwager/sketchbook/hardware/mighty-1284p-master/variants/standard
CXXFLAGS_STD = -g -I /home/schwager/sketchbook/hardware/mighty-1284p-master/variants/standard
#
ISP_PROG = usbasp
# from boards.txt
BOARD_TAG = mighty_opt
ALTERNATE_CORE = mighty-1284p-master
# This is set in the boards.txt file.
#F_CPU = 16000000L
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,67 @@
// EnableInterrupt Simple example sketch. Demonstrates operation on a single pin of your choice.
// See https://github.com/GreyGnome/EnableInterrupt and the README.md for more information.
#include <EnableInterrupt.h>
// Modify this at your leisure. Refer to https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
#if defined __AVR_ATmega640__ || defined __AVR_ATmega2560__ || defined __AVR_ATmega1280__ || \
defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
#define ARDUINOPIN 10
#else
// Pin 7 is useful on Arduino Uno, Leonardo, Mighty1284, ATtiny84...
#define ARDUINOPIN 7
#endif
volatile uint16_t interruptCount=0; // The count will go back to 0 after hitting 65535.
void interruptFunction() {
interruptCount++;
}
void setup() {
Serial.begin(115200);
#ifdef MIGHTY1284
DDRA=0x0; DDRB=0x0; DDRC=0x0; DDRD=0x0; // set all pins as inputs
PORTA=0xFF; PORTB=0xFF; PORTC=0xFF; PORTD=0xFF; // turn on all pullup resistors.
#else
pinMode(ARDUINOPIN, INPUT_PULLUP); // See http://arduino.cc/en/Tutorial/DigitalPins
#endif
enableInterrupt(ARDUINOPIN, interruptFunction, CHANGE);
}
// In the loop we just display interruptCount. The value is updated by the interrupt routine.
void loop() {
Serial.println("---------------------------------------");
delay(1000);
Serial.print("Pin was interrupted: ");
Serial.print(interruptCount, DEC);
Serial.println(" times so far.");
}
//////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// GORY DETAILS //////////////////////////////////////
// This has only been tested on an Arduino Duemilanove and Mega ADK.
// It is designed to work with the Arduino Duemilanove/Uno, Arduino Mega2560/ADK, the Arduino
// Leonardo, and the Arduino Due. Please let me know how you fare on the Leonardo or Due.
// To use:
// 1. You must be using a fairly recent version of the Arduino IDE software on your PC/Mac,
// that is, version 1.0.1 or later. Check Help->About Arduino in the IDE.
// 2. Wire a simple switch to any Analog or Digital pin (known as ARDUINOPIN, defined below)
// that supports interrupts. See https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
// Attach the other end to a GND pin. A "single pole single throw momentary contact normally
// open" // pushbutton switch is best for the most interrupting fun.
// See https://www.sparkfun.com/products/97 and https://octopart.com/b3f-1000-omron-3117
// 3. When pressed, the switch will connect the pin to ground ("low", or "0") voltage, and interrupt the
// processor. See http://arduino.cc/en/Tutorial/DigitalPins
// 4. The interrupt is serviced immediately, and the ISR (Interrupt SubRoutine) modifies the value of
// the global variable interruptCount. Open Tools->Serial Monitor in the IDE to see the results of your
// interrupts.
// 5. Peruse the Examples directory for more elaborate examples.
// 6. Create your own sketch using the EnableInterrupt library!

عرض الملف

@@ -0,0 +1,47 @@
// EnableInterrupt Simple example sketch. Demonstrates operation on a single pin of your choice.
// See https://github.com/GreyGnome/EnableInterrupt and the README.md for more information.
#include <EnableInterrupt.h>
// Modify this at your leisure. Refer to https://github.com/GreyGnome/EnableInterrupt/wiki/Usage#Summary
#define ARDUINOPIN 10
volatile uint16_t interruptCount=0; // The count will go back to 0 after hitting 65535.
void interruptFunction() {
interruptCount++;
}
void setup() {
Serial.begin(115200);
pinMode(ARDUINOPIN, INPUT_PULLUP); // See http://arduino.cc/en/Tutorial/DigitalPins
enableInterrupt(ARDUINOPIN, interruptFunction, CHANGE);
}
// In the loop we just display interruptCount. The value is updated by the interrupt routine.
void loop() {
Serial.println("---------------------------------------");
delay(1000);
Serial.print("Pin was interrupted: ");
Serial.print(interruptCount, DEC);
Serial.println(" times so far.");
}
//////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// GORY DETAILS //////////////////////////////////////
/* The EnableInterrupt library was designed to present a single API for interrupts to all
* the Arduino processors. The problems have traditionally been caused by the varying and
* complicated pin interrupt schemes of the ATmega line of processors. The SAM processors
* present a more straightforward interrupt design. They already do what the EnableInterrupt
* library is trying to present: To enable an interrupt on a pin, simply set up that pin
* with the type of interrupt you want, no conversion to an "Interrupt Number" [see the
* attachInterrupt() docs].
*
* This means that the EnableInterrupt library's work on the Due and Zero is trivial: if
* called on those platforms, we simply create a macro that converts enableInterrupt() and
* disableInterrupt() to attachInterrupt()/detachInterrupt().
*
* Since that's all it does, the ONLY advantage the EnableInterrupt library offers is as
* a consistent API across the chip families. If you are not interested in this then don't use
* the EnableInterrupt library.
*/

عرض الملف

@@ -0,0 +1,14 @@
# Arduino Makefile, see https://github.com/sudar/Arduino-Makefile (it's awesome!)
BOARD_TAG = pro
BOARD_SUB = 16MHzatmega328
ARDUINO_PORT = /dev/ttyUSB0
#BOARD_TAG = 2560
#ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_DIR = /usr
CFLAGS_STD = -g
CXXFLAGS_STD = -g
include /usr/share/arduino/Arduino.mk

عرض الملف

@@ -0,0 +1,39 @@
// SimpleWithLibrary example sketch for the EnableInterrupt library. Demonstrates how to use
// the EnableInterrupt library with a sketch that services an interrupt pin, and uses a library
// that also requires the EnableInterrupt library.
// This sketch has only been compiled to the Arduino Uno (ATmega328).
// This sketch is only known to compile. It has not been tested functionally.
// See https://github.com/GreyGnome/EnableInterrupt and the README.md for more information.
#define EI_ARDUINO_INTERRUPTED_PIN
#include <EnableInterrupt.h>
#define USELESSPIN 10
#include "Useless.h"
#define ARDUINOPIN 9
volatile uint16_t interruptCount=0;
void interruptFunction() {
interruptCount++;
}
// UselessClass uses the EnableInterrupt library.
UselessClass uselessObject=UselessClass(USELESSPIN, CHANGE);
void setup() {
Serial.begin(115200);
pinMode(ARDUINOPIN, INPUT_PULLUP); // See http://arduino.cc/en/Tutorial/DigitalPins
enableInterrupt(ARDUINOPIN, interruptFunction, CHANGE);
}
void loop() {
Serial.println("---------------------------------------");
delay(1000);
Serial.print("Pin was interrupted: ");
Serial.print(interruptCount, DEC);
Serial.println(" times so far.");
Serial.print("Useless interrupt count: ");
Serial.print(uselessObject.getUselessVariable(), DEC);
}

عرض الملف

@@ -0,0 +1,26 @@
// FOR TESTING, TO DEMONSTRATE HOW TO USE ENABLEINTERRUPT IN A LIBRARY.
// See Useless.h for more information.
#include "Useless.h"
volatile uint8_t uselessVariable=0;
void uselessFunction() {
uselessVariable++;
}
void UselessClass::init(uint8_t pin, uint8_t mode) {
pinMode(pin, INPUT_PULLUP);
enableInterrupt(pin, uselessFunction, mode);
}
uint8_t UselessClass::getUselessVariable() {
return uselessVariable;
}
void UselessClass::reset() {
uselessVariable=0;
}
void UselessClass::disable(uint8_t pin) {
disableInterrupt(pin);
}

عرض الملف

@@ -0,0 +1,28 @@
// This is a useless library. To use such a useless thing, with the EnableInterrupt library,
// you need to #define LIBCALL_ENABLEINTERRUPT in your library, like so:
#define LIBCALL_ENABLEINTERRUPT
// Thus, none of the functions or ISRs will get compiled but their prototypes are declared
// so you can use them as illustrated in the Useless.cpp.
// You also need to #include the EnableInterrupt.h file in your sketch. After you #include the
// EnableInterrupt.h file, #include the library's .h file (ie, this one in this example). This
// will compile the requisite components. See the SimpleWithLibrary.ino sketch.
#include <stdint.h>
#include <Arduino.h>
#define EI_ARDUINO_INTERRUPTED_PIN
#include <EnableInterrupt.h>
class UselessClass {
public:
UselessClass(uint8_t pin, uint8_t mode) {
init(pin, mode);
}
uint8_t getUselessVariable();
void reset();
void disable(uint8_t pin);
private:
void init(uint8_t pin, uint8_t mode);
};

عرض الملف

@@ -0,0 +1,100 @@
// include the EnableInterrupt library - see the links in the related topics section above for details
#define EI_ARDUINO_INTERRUPTED_PIN // to enable pin states functionality
#include <EnableInterrupt.h>
//DEBUG settings
#define DEBUG 1 // 0 - no debug
// Assign your channel in pins
#define CHANNEL1_IN_PIN 2
#define CHANNEL2_IN_PIN 3
#define CHANNEL3_IN_PIN 4
#define CHANNEL4_IN_PIN 5
#define CHANNEL5_IN_PIN 6
#define CHANNEL6_IN_PIN 7
#define CHANNEL7_IN_PIN 8
#define CHANNEL8_IN_PIN 9
volatile uint16_t interruptCountA=0; // The count will go back to 0 after hitting 65535.
volatile uint16_t PinStateSumB=0; // The count will go back to 0 after hitting 65535.
// shared variables are updated by the ISR and read by loop.
// In loop we immediatley take local copies so that the ISR can keep ownership of the
// shared ones. To access these in loop
// we first turn interrupts off with noInterrupts
// we take a copy to use in loop and the turn interrupts back on
// as quickly as possible, this ensures that we are always able to receive new signals
volatile uint8_t InterruptedPinShared;
volatile uint8_t PinStateShared;
void setup()
{
if (DEBUG !=0) {
Serial.begin(9600);
Serial.println("setup started ");
}
enableInterrupt(CHANNEL1_IN_PIN, interruptFunction,CHANGE);
enableInterrupt(CHANNEL2_IN_PIN, interruptFunction,CHANGE);
if (DEBUG !=0) {
Serial.println(" setup completed ");
}
}
void loop()
{
static uint8_t InterruptedPin;
static uint8_t PinState;
noInterrupts(); // turn interrupts off quickly while we take local copies of the shared variables
InterruptedPin = InterruptedPinShared;
PinState = PinStateShared;
interrupts(); // we have local copies of the inputs, so now we can turn interrupts back on
// as soon as interrupts are back on, we can no longer use the shared variables here
//Printing
if (DEBUG !=0) {
Serial.print("interruptCountA:");
Serial.print(interruptCountA);
Serial.println("");
Serial.print("PinStateSumB:");
Serial.print(PinStateSumB);
Serial.println("");
Serial.print("InterruptedPin:");
Serial.print(InterruptedPin);
Serial.println("");
Serial.print("PinState:");
Serial.print(PinState);
Serial.println("");
}
}// end of loop
void interruptFunction() {
//interruptCountA increased each time interrupt called
interruptCountA++;
//save values to use them outside the interrupt function
InterruptedPinShared=arduinoInterruptedPin;
PinStateShared=arduinoPinState;
//PinStateSumB increased each time arduinoPinState=1 detected
PinStateSumB=PinStateSumB + arduinoPinState ;
}

عرض الملف

@@ -0,0 +1,24 @@
#!/bin/bash
examples="
AllPins2560
AllPins328
ATtinyBlink
HiSpeed
HiSpeedAllPins2560
HiSpeedAllPins328
InterruptedPin2560
InterruptedPin328
Mighty1284p
OOSimple
Simple
SimpleWithLibrary
"
for example in $examples; do
echo $example
sleep 2
( cd $example; rm -rf build-*; make)
echo $example done
sleep 2
done

عرض الملف

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

عرض الملف

@@ -0,0 +1,19 @@
NOTICE
EnableInterrupt Arduino Library
Copyright 2014-2015 Michael Schwager (aka Mike Schwager aka "GreyGnome")
This product includes software developed by Mike Schwager.
This library was inspired and replaces the PinChangeInt library.
GreyGnome is the current maintainer, and would like to thank all those
Open Source coders, the Arduino makers and community, and especially Chris
and Lex for lighting the flame and showing the way! And a big thank you to
the users who have contributed comments and bug fixes along the way.
Without you this project would not have overcome some significant hurdles.
A HUGE thanks to Jan Baeyens ("jantje"), who has graciously DONATED an
Arduino Mega ADK board to the PinChangeInt project!!! Wow, thanks Jan!
This makes the 2560-based Arduino Mega a first class supported platform-
I am able to test it and verify that it works.

عرض الملف

@@ -0,0 +1,92 @@
Wed Sep 4 19:30:45 CDT 2019
Version 1.1.0
We add support for the ATmega2561 and 1281 chips, with pinouts defined from the MCUdude/MegaCore project. Code donations by Kizmit99. Plus, a documentation bugfix from Greg Bowler. Thanks, folks!
Fri Jun 22 06:47:13 CDT 2018
Version 1.0.0
Alex Reinert contributed Bobuino support. Thanks, Alex! And at this point, I think it's long past due that we stick a non-beta sticker on this thing. Congratulations, EnableInterrupt- you are all grown up. Version 1.0.0 it is.
Tue Sep 19 18:02:21 CDT 2017
Version 0.9.8.
There were a number of outstanding pull requests that were merged into the library. Thanks
to Loranzo Cafaro for his switch debounce example, to Jevon Wild for his changes to make the
library more functional with PlatformIO (http://docs.platformio.org/en/latest/what-is-platformio.html),
Ricardo JL Rufino for some PlatformIO fixes to the library.json file, and Sara Damiano for
adding support for the Sodaq Mbili and EnviroDIY Mayfly.
Wed Apr 27 18:07:02 CDT 2016
Version 0.9.5 Added the arduinoPinState variable, which is available when EI_INTERRUPTED_PIN is defined. Added support for platformio http://platformio.org/ (thanks dorkusprime!).
Fri Nov 6 19:13:20 CST 2015
Version 0.9.4. Thanks again to RobertClemenzi, who discovered 2 bugs: 1. A spurious comma in some array definitions caused a compiler warning, and more importantly, 2. it was impossible to use arduinoInterruptedPin if this library was used to support other libraries. Fixed them both.
Mon Oct 19 07:45:08 CDT 2015
Version 0.9.3. Thanks to RobertClemenzi, who pointed out that "Useless.cpp" is not included with the distribution zip file. The only change is to add that file to the distribution zip file.
Sat Oct 17 12:03:03 CDT 2015
Version 0.9.2. I discovered a rather pernicious bug, wherein the library was setting the global interrupt enable bit. This could cause a serious and difficult-to-debug race condition, as it is not the job of the library to manage that bit. The chips come with interrupts enabled so exi
sting code should not be affected. My thanks to http://gammon.com.au/interrupts (the 'How are interrupts queued?' section).
Fri Oct 16 07:58:45 CDT 2015
Version 0.9.1. Bug fixes to examples/OOSimple (thanks RobertClemenzi!). Arduino Zero support added (this is a trivial preprocessor macro check; see the Usage wiki page). Wiki pages updated, especially the FAQ.
Tue Sep 29 06:34:58 CDT 2015
Version 0.9.0. ATtiny support has been added! Support files come from https://github.com/damellis/attiny .
Chips supported include ATtiny44/84 and ATtiny 45/85 (including Gemma). As always, bug reports are
welcome at https://github.com/GreyGnome/EnableInterrupt/issues . NOTE: I don't have an ATtiny (yet),
so the only work I could do was to make sure a sample sketch compiled.
Thu Aug 27 22:24:39 CDT 2015
Version 0.8.2. Includes bugfixes for issues raised by engwan, MakkyB, and juanricos; HiSpeed mode was not working but now it is. I also received some nice bug reports and testing from TomWS1. Finally, the library.properties file was out of date.
Sat Aug 8 12:03:24 CDT 2015
Version 0.8.1. I forgot to include some fixes for an issue on the website; https://github.com/GreyGnome/EnableInterrupt/issues/13 (having to do with the 1284 chip). These are now included.
Fri Aug 7 06:44:55 CDT 2015
Version 0.8.0. This release includes the function to set a variable that can be queried by the programmer's
ISR, to determine which pin was interrupted. Define EI_ARDUINO_INTERRUPTED_PIN in the main sketch.
Also:
My Mega2560 failed right in the middle of testing this release. So that platform is not fully tested.
The InterruptedPin2560.ino sketch was giving me some inconsistent results: I saw pin 71 interrupted twice,
and pin 70 not at all. I think there is a bug in utility/ei_PinChange2560.h, but I will release before I resolve
this. If there is anyone who could test on the 2560 platform- run the InterruptedPin2560.ino sketch and send me
the output- I would appreciate it.
Mon Jul 6 17:41:05 CDT 2015
This release includes compiler directives that allow you to eliminate unneeded ports and memory allocations, to more efficiently utilize code and static RAM. See https://github.com/GreyGnome/EnableInterrupt/wiki/SaveMemory for the new features.
Tue Jun 23 06:47:10 CDT 2015
Version 0.6.3 of the library has been released. This release includes an Object Oriented example, OOSimple, in the examples/ directory. There are no other changes since version 0.6.2.
Fri Jun 19 09:38:43 CDT 2015
Version 0.6.2. Forgot to update README.md.
Fri Jun 12 06:33:20 CDT 2015
Version 0.6.1 of the library has been released. This version is designed to meet the requirements of the 1.5.x Arduino library spec. No code logic was modified; only files were moved and library.properties and keywords.txt files added.
Version 0.6.0 did not include an update to these release notes.
Fri Jun 12 06:33:20 CDT 2015
Version 0.5 (Alpha) of the library has been released. This release includes support for the ATmega1284p line of processors (includes ATmega644). The Mighty 1284 is used as the basis. As I don't have a 1284-based processor, this code compiles but has not been tested (see examples/Might1284p). Bug reports encouraged and welcomed! It would be great if a 644/1284 owner could upload the Might1284p.ino sketch and interrupt every pin and let me know the results.
Code was refactored so that a lot of utility routines were moved into individual .h files. Now there's a lot of files, which appears ugly, but the old way was a lot uglier to my mind and looked like a big bowl of spaghetti with so many #ifdefs strewn about to handle the different chips. It was getting hard to wade through the code.
Fri May 8 07:33:26 CDT 2015
Version 0.4 - New high speed ("HiSpeed") mode. In this mode, the interrupt routine is predefined:
it ONLY updates a variable. This knocks a couple of microseconds off of the interrupt
routine times; it greatly reduces the number of registers needed to be pushed/popped, and
of course does not require a function call. See the wiki for details, including speed measurements.
Mon Apr 13 07:49:05 CDT 2015
Version 0.3 - Arjun reported a bug on the Uno platform:
In file included from Interrupt.ino:1:
/Users/arjunmehta94/Documents/Arduino/libraries/EnableInterrupt-master/EnableInterrupt.h: In function 'void __vector_3()':
/Users/arjunmehta94/Documents/Arduino/libraries/EnableInterrupt-master/EnableInterrupt.h:976: error: 'struct functionPointersPortB' has no member named 'pinSix'
/Users/arjunmehta94/Documents/Arduino/libraries/EnableInterrupt-master/EnableInterrupt.h:977: error: 'struct functionPointersPortB' has no member named 'pinSeven'
I have a Duemilanove; I don't know why I never saw that error. Regardless, I have included some
#ifndef lines in to protect that code from getting compiled.
Also added RELEASE_NOTES to the zip file, and to Git.

عرض الملف

@@ -0,0 +1,13 @@
#!/bin/bash
# A utility program for looking for stuff in the #include directories on my system.
# Tracked so I have a backup of it.
arduinoToo=false
[ "$1" = "-a" ] && arduinoToo=true && shift
find /usr/avr/include /usr/lib/gcc/avr/*/include /usr/lib/gcc/avr/*/include-fixed \
/usr/lib/gcc/avr/*/plugin/include \
-type f -exec grep "$1" {} \; -print
$arduinoToo && find /usr/share/arduino \
-type f -exec grep "$1" {} \; -print

عرض الملف

@@ -0,0 +1,20 @@
#######################################
# Syntax Coloring Map For EnableInterrupt
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
enableInterrupt KEYWORD2
disableInterrupt KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
PINCHANGEINTERRUPT LITERAL1

عرض الملف

@@ -0,0 +1,20 @@
{
"name": "EnableInterrupt",
"version": "1.1.0",
"frameworks": "arduino",
"platforms" : "atmelavr",
"keywords": "interrupt, interrupts, pin, pins",
"description": "Assign an interrupt to any supported pin on all Arduinos, plus ATtiny 84/85 and ATmega 644/1284.",
"authors": [
{
"name": "Mike 'GreyGnome' Schwager",
"email": "mschwage@gmail.com",
"url": "https://github.com/GreyGnome",
"maintainer": true
}
],
"repository": {
"type": "git",
"url": "https://github.com/GreyGnome/EnableInterrupt"
}
}

عرض الملف

@@ -0,0 +1,9 @@
name=EnableInterrupt
version=1.1.0
author=Mike "GreyGnome" Schwager <mschwage@gmail.com>
maintainer=Mike "GreyGnome" Schwager <mschwage@gmail.com>
sentence=Assign an interrupt to any supported pin on all Arduinos, plus ATtiny 84/85 and ATmega 644/1284.
paragraph=Provides a consistent API across chips, architectures, and interrupt types. Makes External and Pin Change on the ATmega series, and Due and Zero pin interrupts operate similarly. Code optimized for speed; includes an extra-high-speed mode for speed critical code.
category=Signal Input/Output
url=https://github.com/GreyGnome/EnableInterrupt
architectures=*

عرض الملف

@@ -0,0 +1,66 @@
#if ! defined(EI_NOTINT0) && ! defined (EI_NOTINT1) && ! defined (EI_NOTINT2)
#ifdef EI_SECTION_ENABLEEXTERNAL
switch (arduinoPin) {
#ifndef EI_NOTINT0
case ARDUINO_PIN_D2 : // INT0 (Either 2 or 10)
EIMSK &= ~_BV(0);
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[0] = userFunction;
#endif
EICRA &= (~_BV(0) & ~_BV(1)); // reset the flags prior to
EICRA |= mode; // set them the way we want
EIFR |= _BV(0);
EIMSK |= _BV(0);
break;
#endif
#ifndef EI_NOTINT1
case ARDUINO_PIN_D3 : // INT1 (Either 3 or 11)
EIMSK &= ~_BV(1);
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[1] = userFunction;
#endif
EICRA &= (~_BV(2) & ~_BV(3));
EICRA |= (mode << 2);
EIFR |= _BV(1);
EIMSK |= _BV(1);
break;
#endif
#ifndef EI_NOTINT2
case ARDUINO_PIN_B2 : // INT2 (Either 10 or 2)
EIMSK &= ~_BV(2);
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[2] = userFunction;
#endif
EICRA &= (~_BV(4) & ~_BV(5));
EICRA |= (mode << 4);
EIFR |= _BV(2);
EIMSK |= _BV(2);
break;
#endif
}
#endif // EI_SECTION_ENABLEEXTERNAL
#ifdef EI_SECTION_DISABLEEXTERNAL
#ifndef EI_NOTINT0
if (arduinoPin == ARDUINO_PIN_D2) { // INT0 (Either 2 or 10)
EIMSK &= ~_BV(0);
EICRA &= (~_BV(0) & ~_BV(1));
EIFR |= _BV(0); // using a clue from the ATmega2560 datasheet.
}
#endif
#ifndef EI_NOTINT1
if (arduinoPin == ARDUINO_PIN_D3) { // INT1 (Either 3 or 11)
EIMSK &= ~_BV(1);
EICRA &= (~_BV(2) & ~_BV(3));
EIFR |= _BV(1); // using a clue from the ATmega2560 datasheet.
}
#endif
#ifndef EI_NOTINT2
if (arduinoPin == ARDUINO_PIN_B2) { // INT2 (Either 10 or 2)
EIMSK &= ~_BV(2);
EICRA &= (~_BV(4) & ~_BV(5));
EIFR |= _BV(2); // using a clue from the ATmega2560 datasheet.
}
#endif
#endif // EI_SECTION_DISABLEEXTERNAL
#endif // ! defined(EI_NOTINT0) && ! defined (EI_NOTINT1) && ! defined (EI_NOTINT2)

عرض الملف

@@ -0,0 +1,228 @@
#if ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2) && ! defined(EI_NOTINT3) && ! defined(EI_NOTINT4) && ! defined(EI_NOTINT5) && ! defined(EI_NOTINT6) && ! defined(EI_NOTINT7)
#ifdef EI_SECTION_ENABLEEXTERNAL
switch (arduinoPin) {
#ifndef EI_NOTINT0
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 18 : // INT0 (xxx1 - MegaCore pinout)
#else
case 21 : // INT0
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[0] = userFunction;
#endif
EIMSK &= ~_BV(0);
EICRA &= (~_BV(0) & ~_BV(1));
EICRA |= mode;
EIFR |= _BV(0);
EIMSK |= _BV(0);
break;
#endif
#ifndef EI_NOTINT1
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 19 : // INT1
#else
case 20 : // INT1
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[1] = userFunction;
#endif
EIMSK &= ~_BV(1);
EICRA &= (~_BV(2) & ~_BV(3));
EICRA |= (mode << 2);
EIFR |= _BV(1);
EIMSK |= _BV(1);
break;
#endif
#ifndef EI_NOTINT2
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 20 : // INT2
#else
case 19 : // INT2
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[2] = userFunction;
#endif
EIMSK &= ~_BV(2);
EICRA &= (~_BV(4) & ~_BV(5));
EICRA |= (mode << 4);
EIFR |= _BV(2);
EIMSK |= _BV(2);
break;
#endif
#ifndef EI_NOTINT3
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 21 : // INT3
#else
case 18 : // INT3
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[3] = userFunction;
#endif
EIMSK &= ~_BV(3);
EICRA &= (~_BV(6) & ~_BV(7));
EICRA |= (mode << 6);
EIFR |= _BV(3);
EIMSK |= _BV(3);
break;
#endif
#ifndef EI_NOTINT4
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 4 : // INT4
#else
case 2 : // INT4
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[4] = userFunction;
#endif
EIMSK &= ~_BV(4);
EICRB &= (~_BV(0) & ~_BV(1));
EICRB |= mode;
EIFR |= _BV(4);
EIMSK |= _BV(4);
break;
#endif
#ifndef EI_NOTINT5
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 5 : // INT5
#else
case 3 : // INT5
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[5] = userFunction;
#endif
EIMSK &= ~_BV(5);
EICRB &= (~_BV(2) & ~_BV(3));
EICRB |= (mode << 2);
EIFR |= _BV(5);
EIMSK |= _BV(5);
break;
#endif
#ifndef EI_NOTINT6
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 6 : // INT6
#else
case 75 : // INT6- Fake Arduino Pin
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[6] = userFunction;
#endif
EIMSK &= ~_BV(6);
EICRB &= (~_BV(4) & ~_BV(5));
EICRB |= (mode << 4);
EIFR |= _BV(6);
EIMSK |= _BV(6);
break;
#endif
#ifndef EI_NOTINT7
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 7 : // INT7
#else
case 76 : // INT7- Fake Arduino Pin
#endif
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[7] = userFunction;
#endif
EIMSK &= ~_BV(7);
EICRB &= (~_BV(6) & ~_BV(7));
EICRB |= (mode << 6);
EIFR |= _BV(7);
EIMSK |= _BV(7);
break;
#endif
}
#endif // EI_SECTION_ENABLEEXTERNAL
#ifdef EI_SECTION_DISABLEEXTERNAL
switch (arduinoPin) {
#ifndef EI_NOTINT0
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 18 : // INT0
#else
case 21 : // INT0
#endif
EIMSK &= ~_BV(0);
EICRA &= (~_BV(0) & ~_BV(1));
EIFR |= _BV(0);
break;
#endif
#ifndef EI_NOTINT1
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 19 : // INT1
#else
case 20 : // INT1
#endif
EIMSK &= ~_BV(1);
EICRA &= (~_BV(2) & ~_BV(3));
EIFR |= _BV(1);
break;
#endif
#ifndef EI_NOTINT2
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 20 : // INT2
#else
case 19 : // INT2
#endif
EIMSK &= ~_BV(2);
EICRA &= (~_BV(4) & ~_BV(5));
EIFR |= _BV(2);
break;
#endif
#ifndef EI_NOTINT3
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 21 : // INT3
#else
case 18 : // INT3
#endif
EIMSK &= ~_BV(3);
EICRA &= (~_BV(6) & ~_BV(7));
EIFR |= _BV(3);
break;
#endif
#ifndef EI_NOTINT4
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 4 : // INT4
#else
case 2 : // INT4
#endif
EIMSK &= ~_BV(4);
EICRB &= (~_BV(0) & ~_BV(1));
EIFR |= _BV(4);
break;
#endif
#ifndef EI_NOTINT5
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 5 : // INT5
#else
case 3 : // INT5
#endif
EIMSK &= ~_BV(5);
EICRB &= (~_BV(2) & ~_BV(3));
EIFR |= _BV(5);
break;
#endif
#ifndef EI_NOTINT6
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 6 : // INT6
#else
case 75 : // INT6- Fake Arduino Pin
#endif
EIMSK &= ~_BV(6);
EICRB &= (~_BV(4) & ~_BV(5));
EIFR |= _BV(6);
break;
#endif
#ifndef EI_NOTINT7
#if defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
case 7 : // INT7
#else
case 76 : // INT7- Fake Arduino Pin
#endif
EIMSK &= ~_BV(7);
EICRB &= (~_BV(6) & ~_BV(7));
EIFR |= _BV(7);
break;
#endif
}
#endif // EI_SECTION_DISABLEEXTERNAL
#endif // ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2) && ! defined(EI_NOTINT3) && ! defined(EI_NOTINT4) && ! defined(EI_NOTINT5) && ! defined(EI_NOTINT6) && ! defined(EI_NOTINT7)

عرض الملف

@@ -0,0 +1,45 @@
#if ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1)
#ifdef EI_SECTION_ENABLEEXTERNAL
#ifndef EI_NOTINT0
if (arduinoPin == 2) {
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[0] = userFunction;
#endif
EIMSK &= ~_BV(0);
EICRA &= (~_BV(0) & ~_BV(1));
EICRA |= mode;
EIFR |= _BV(0); // using a clue from the ATmega2560 datasheet.
EIMSK |= _BV(0);
}
#endif
#ifndef EI_NOTINT1
if (arduinoPin == 3) {
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[1] = userFunction;
#endif
EIMSK &= ~_BV(1);
EICRA &= (~_BV(2) & ~_BV(3));
EICRA |= mode << 2;
EIFR |= _BV(1); // using a clue from the ATmega2560 datasheet.
EIMSK |= _BV(1);
}
#endif
#endif // EI_SECTION_ENABLEEXTERNAL
#ifdef EI_SECTION_DISABLEEXTERNAL
#ifndef EI_NOTINT0
if (arduinoPin == 2) {
EIMSK &= ~_BV(0);
EICRA &= (~_BV(0) & ~_BV(1));
EIFR |= _BV(0); // using a clue from the ATmega2560 datasheet.
}
#endif
#ifndef EI_NOTINT1
if (arduinoPin == 3) {
EIMSK &= ~_BV(1);
EICRA &= (~_BV(2) & ~_BV(3));
EIFR |= _BV(1); // using a clue from the ATmega2560 datasheet.
}
#endif
#endif // EI_SECTION_DISABLEEXTERNAL
#endif // ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1)

عرض الملف

@@ -0,0 +1,106 @@
#if ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2) && ! defined(EI_NOTINT3) && ! defined(EI_NOTINT6)
#ifdef EI_SECTION_ENABLEEXTERNAL
switch (arduinoPin) {
#ifndef EI_NOTINT0
case 3 : // INT0
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[0] = userFunction;
#endif
EIMSK &= ~_BV(0);
EICRA &= (~_BV(0) & ~_BV(1));
EICRA |= mode;
EIFR |= _BV(0);
EIMSK |= _BV(0);
break;
#endif
#ifndef EI_NOTINT1
case 2 : // INT1
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[1] = userFunction;
#endif
EIMSK &= ~_BV(1);
EICRA &= (~_BV(2) & ~_BV(3));
EICRA |= (mode << 2);
EIFR |= _BV(1);
EIMSK |= _BV(1);
break;
#endif
#ifndef EI_NOTINT2
case 0 : // INT2
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[2] = userFunction;
#endif
EIMSK &= ~_BV(2);
EICRA &= (~_BV(4) & ~_BV(5));
EICRA |= (mode << 4);
EIFR |= _BV(2);
EIMSK |= _BV(2);
break;
#endif
#ifndef EI_NOTINT3
case 1 : // INT3
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[3] = userFunction;
#endif
EIMSK &= ~_BV(3);
EICRA &= (~_BV(6) & ~_BV(7));
EICRA |= (mode << 6);
EIFR |= _BV(3);
EIMSK |= _BV(3);
break;
#endif
#ifndef EI_NOTINT6
case 7 : // INT6
#ifndef NEEDFORSPEED
functionPointerArrayEXTERNAL[4] = userFunction;
#endif
EIMSK &= ~_BV(6);
EICRB &= (~_BV(4) & ~_BV(5));
EICRB |= (mode << 4);
EIFR |= _BV(6);
EIMSK |= _BV(6);
break;
#endif
}
#endif // EI_SECTION_ENABLEEXTERNAL
#ifdef EI_SECTION_DISABLEEXTERNAL
switch (arduinoPin) {
#ifndef EI_NOTINT0
case 3 : // INT0
EIMSK &= ~_BV(0);
EICRA &= (~_BV(0) & ~_BV(1));
EIFR |= _BV(0);
break;
#endif
#ifndef EI_NOTINT1
case 2 : // INT1
EIMSK &= ~_BV(1);
EICRA &= (~_BV(2) & ~_BV(3));
EIFR |= _BV(1);
break;
#endif
#ifndef EI_NOTINT2
case 0 : // INT2
EIMSK &= ~_BV(2);
EICRA &= (~_BV(4) & ~_BV(5));
EIFR |= _BV(2);
break;
#endif
#ifndef EI_NOTINT3
case 1 : // INT3
EIMSK &= ~_BV(3);
EICRA &= (~_BV(6) & ~_BV(7));
EIFR |= _BV(3);
break;
#endif
#ifndef EI_NOTINT6
case 7 : // INT6
EIMSK &= ~_BV(6);
EICRB &= (~_BV(4) & ~_BV(5));
EIFR |= _BV(6);
break;
#endif
}
#endif // EI_SECTION_DISABLEEXTERNAL
#endif // ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2) && ! defined(EI_NOTINT3) && ! defined(EI_NOTINT6)

عرض الملف

@@ -0,0 +1,24 @@
// Support for the 14-pin ATtiny24/24A/44/44A/84/84A
#if ! defined(EI_NOTINT0)
#ifdef EI_SECTION_ENABLEEXTERNAL
// NO switch (arduinoPin) { // ONLY 1 External Interrupt pin.
#ifndef EI_NOTINT0
GIMSK &= ~_BV(6); // Disable interrupts since we are (possibly) changing interrupt settings
#ifndef NEEDFORSPEED
externalFunctionPointer = userFunction;
#endif
MCUCR &= (~_BV(0) & ~_BV(1)); // reset the flags prior to
MCUCR |= mode; // set them the way we want
GIFR |= _BV(6);
GIMSK |= _BV(6);
#endif
#endif // EI_SECTION_ENABLEEXTERNAL
#ifdef EI_SECTION_DISABLEEXTERNAL
#ifndef EI_NOTINT0
GIMSK &= ~_BV(6);
MCUCR &= (~_BV(0) & ~_BV(1)); // reset the flags
GIFR |= _BV(6); // using a clue from the ATmega2560 datasheet.
#endif
#endif // EI_SECTION_DISABLEEXTERNAL
#endif // ! defined(EI_NOTINT0) && ! defined (EI_NOTINT1) && ! defined (EI_NOTINT2)

عرض الملف

@@ -0,0 +1,22 @@
// Support for the 8-pin ATtiny25/45/85
#ifdef EI_SECTION_ENABLEEXTERNAL
// NO switch (arduinoPin) { // ONLY 1 External Interrupt pin.
#ifndef EI_NOTINT0
GIMSK &= ~_BV(6);
#ifndef NEEDFORSPEED
externalFunctionPointer = userFunction;
#endif
MCUCR &= (~_BV(0) & ~_BV(1)); // reset the flags prior to
MCUCR |= mode; // set them the way we want
GIFR |= _BV(6);
GIMSK |= _BV(6);
#endif // ! defined (EI_NOTINT0)
#endif // EI_SECTION_ENABLEEXTERNAL
#ifdef EI_SECTION_DISABLEEXTERNAL
#ifndef EI_NOTINT0
GIMSK &= ~_BV(6);
GIFR |= _BV(6); // using a clue from the ATmega2560 datasheet.
MCUCR &= (~_BV(0) & ~_BV(1));
#endif
#endif // EI_SECTION_DISABLEEXTERNAL

عرض الملف

@@ -0,0 +1,127 @@
#ifdef EI_SECTION_RISING
#ifndef EI_NOTPORTA
if (portNumber==PA) {
risingPinsPORTA |= portMask;
}
#endif
#ifndef EI_NOTPORTB
if (portNumber==PB) {
risingPinsPORTB |= portMask;
}
#endif
#ifndef EI_NOTPORTC
if (portNumber==PC) {
risingPinsPORTC |= portMask;
}
#endif
#ifndef EI_NOTPORTD
if (portNumber==PD) {
risingPinsPORTD |= portMask;
}
#endif
#endif // EI_SECTION_RISING
#ifdef EI_SECTION_FALLING
#ifndef EI_NOTPORTA
if (portNumber==PA) {
fallingPinsPORTA |= portMask;
}
#endif
#ifndef EI_NOTPORTB
if (portNumber==PB) {
fallingPinsPORTB |= portMask;
}
#endif
#ifndef EI_NOTPORTC
if (portNumber==PC) {
fallingPinsPORTC |= portMask;
}
#endif
#ifndef EI_NOTPORTD
if (portNumber==PD) {
fallingPinsPORTD |= portMask;
}
#endif
#endif // EI_SECTION_FALLING
#if defined EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifndef EI_NOTPORTA
if (portNumber==PA) {
#ifndef NEEDFORSPEED
calculatedPointer=&portAFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotA=*portInputRegister(portNumber);
pcmsk=&PCMSK0;
PCICR |= _BV(0);
}
#endif
#ifndef EI_NOTPORTB
if (portNumber==PB) {
#ifndef NEEDFORSPEED
calculatedPointer=&portBFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotB=*portInputRegister(portNumber);
pcmsk=&PCMSK1;
PCICR |= _BV(1);
}
#endif
#ifndef EI_NOTPORTC
if (portNumber==PC) {
#ifndef NEEDFORSPEED
calculatedPointer=&portCFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotC=*portInputRegister(portNumber);
pcmsk=&PCMSK2;
PCICR |= _BV(2);
}
#endif
#ifndef EI_NOTPORTD
if (portNumber==PD) {
#ifndef NEEDFORSPEED
calculatedPointer=&portDFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotD=*portInputRegister(portNumber);
pcmsk=&PCMSK3;
PCICR |= _BV(3);
}
#endif
#endif // EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifdef EI_SECTION_DISABLEPINCHANGE
#ifndef EI_NOTPORTA
if (portNumber == PA) {
PCMSK0 &= ~portMask;
if (PCMSK0 == 0) { PCICR &= ~_BV(0); };
risingPinsPORTA &= ~portMask;
fallingPinsPORTA &= ~portMask;
}
#endif
#ifndef EI_NOTPORTB
if (portNumber == PB) {
PCMSK1 &= ~portMask;
if (PCMSK1 == 0) { PCICR &= ~_BV(1); };
risingPinsPORTB &= ~portMask;
fallingPinsPORTB &= ~portMask;
}
#endif
#ifndef EI_NOTPORTC
if (portNumber == PC) {
PCMSK2 &= ~portMask;
if (PCMSK2 == 0) { PCICR &= ~_BV(2); };
risingPinsPORTC &= ~portMask;
fallingPinsPORTC &= ~portMask;
}
#endif
#ifndef EI_NOTPORTD
if (portNumber == PD) {
PCMSK3 &= ~portMask;
if (PCMSK3 == 0) { PCICR &= ~_BV(3); };
risingPinsPORTB &= ~portMask;
fallingPinsPORTB &= ~portMask;
}
#endif
#endif // EI_SECTION_DISABLEPINCHANGE

عرض الملف

@@ -0,0 +1,103 @@
#ifdef EI_SECTION_RISING
#ifndef EI_NOTPORTB
if (portNumber==PB) {
risingPinsPORTB |= portMask;
}
#endif
#ifndef EI_NOTPORTJ
if (portNumber==PJ) {
risingPinsPORTJ |= portMask;
}
#endif
#ifndef EI_NOTPORTK
if (portNumber==PK) {
risingPinsPORTK |= portMask;
}
#endif
#endif
#ifdef EI_SECTION_FALLING
#ifndef EI_NOTPORTB
if (portNumber==PB) {
fallingPinsPORTB |= portMask;
}
#endif
#ifndef EI_NOTPORTJ
if (portNumber==PJ) {
fallingPinsPORTJ |= portMask;
}
#endif
#ifndef EI_NOTPORTK
if (portNumber==PK) {
fallingPinsPORTK |= portMask;
}
#endif
#endif // EI_SECTION_FALLING
#ifdef EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifndef EI_NOTPORTB
if (portNumber==PB) {
#ifndef NEEDFORSPEED
calculatedPointer=&portBFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotB=*portInputRegister(portNumber);
pcmsk=&PCMSK0;
PCICR |= _BV(0);
}
#endif
#ifndef EI_NOTPORTJ
if (portNumber==PJ) {
#ifndef NEEDFORSPEED
calculatedPointer=&portJFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotJ=*portInputRegister(portNumber);
pcmsk=&PCMSK1;
PCICR |= _BV(1);
// TODO: I think the order of these is flipped. Test. BUG??? -Mike
portJPCMSK|=portMask; // because PCMSK1 is shifted wrt. PortJ.
portMask <<= 1; // Handle port J's oddness. PJ0 is actually 1 on PCMSK1.
}
#endif
#ifndef EI_NOTPORTK
if (portNumber==PK) {
#ifndef NEEDFORSPEED
calculatedPointer=&portKFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotK=*portInputRegister(portNumber);
pcmsk=&PCMSK2;
PCICR |= _BV(2);
}
#endif
#endif // EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifdef EI_SECTION_DISABLEPINCHANGE
#ifndef EI_NOTPORTB
if (portNumber == PB) {
PCMSK0 &= ~portMask;
if (PCMSK0 == 0) { PCICR &= ~_BV(0); };
risingPinsPORTB &= ~portMask;
fallingPinsPORTB &= ~portMask;
}
#endif
#ifndef EI_NOTPORTJ
if (portNumber == PJ) {
// Handle port J's oddness. PJ0 is actually 1 on PCMSK1.
PCMSK1 &= ((~portMask << 1) | 0x01); // or with 1 to not touch PE0.
if (PCMSK1 == 0) { PCICR &= ~_BV(1); };
risingPinsPORTJ &= ~portMask;
fallingPinsPORTJ &= ~portMask;
}
#endif
#ifndef EI_NOTPORTK
if (portNumber == PK) {
PCMSK2 &= ~portMask;
if (PCMSK2 == 0) { PCICR &= ~_BV(2); };
risingPinsPORTK &= ~portMask;
fallingPinsPORTK &= ~portMask;
}
#endif
#endif // EI_SECTION_DISABLEPINCHANGE

عرض الملف

@@ -0,0 +1,98 @@
#ifdef EI_SECTION_RISING
#ifndef EI_NOTPORTB
if (portNumber==PB) {
risingPinsPORTB |= portMask;
}
#endif
#ifndef EI_NOTPORTC
if (portNumber==PC) {
risingPinsPORTC |= portMask;
}
#endif
#ifndef EI_NOTPORTD
if (portNumber==PD) {
risingPinsPORTD |= portMask;
}
#endif
#endif // EI_SECTION_RISING
#ifdef EI_SECTION_FALLING
#ifndef EI_NOTPORTB
if (portNumber==PB) {
fallingPinsPORTB |= portMask;
}
#endif
#ifndef EI_NOTPORTC
if (portNumber==PC) {
fallingPinsPORTC |= portMask;
}
#endif
#ifndef EI_NOTPORTD
if (portNumber==PD) {
fallingPinsPORTD |= portMask;
}
#endif
#endif // EI_SECTION_FALLING
#if defined EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifndef EI_NOTPORTB
if (portNumber==PB) {
#ifndef NEEDFORSPEED
calculatedPointer=&portBFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotB=*portInputRegister(portNumber);
pcmsk=&PCMSK0;
PCICR |= _BV(0);
}
#endif
#ifndef EI_NOTPORTC
if (portNumber==PC) {
#ifndef NEEDFORSPEED
calculatedPointer=&portCFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotC=*portInputRegister(portNumber);
pcmsk=&PCMSK1;
PCICR |= _BV(1);
}
#endif
#ifndef EI_NOTPORTD
if (portNumber==PD) {
#ifndef NEEDFORSPEED
calculatedPointer=&portDFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotD=*portInputRegister(portNumber);
pcmsk=&PCMSK2;
PCICR |= _BV(2);
}
#endif
#endif // EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifdef EI_SECTION_DISABLEPINCHANGE
#ifndef EI_NOTPORTB
if (portNumber == PB) {
PCMSK0 &= ~portMask;
if (PCMSK0 == 0) { PCICR &= ~_BV(0); };
risingPinsPORTB &= ~portMask;
fallingPinsPORTB &= ~portMask;
}
#endif
#ifndef EI_NOTPORTC
if (portNumber == PC) {
PCMSK1 &= ~portMask;
if (PCMSK1 == 0) { PCICR &= ~_BV(1); };
risingPinsPORTC &= ~portMask;
fallingPinsPORTC &= ~portMask;
}
#endif
#ifndef EI_NOTPORTD
if (portNumber == PD) {
PCMSK2 &= ~portMask;
if (PCMSK2 == 0) { PCICR &= ~_BV(2); };
risingPinsPORTD &= ~portMask;
fallingPinsPORTD &= ~portMask;
}
#endif
#endif // EI_SECTION_DISABLEPINCHANGE

عرض الملف

@@ -0,0 +1,33 @@
// ALL pin change interrupts are on Port B on Leonardo.
#ifdef EI_SECTION_RISING
#ifndef EI_NOTPORTB
risingPinsPORTB |= portMask;
#endif
#endif // EI_SECTION_RISING
#ifdef EI_SECTION_FALLING
#ifndef EI_NOTPORTB
fallingPinsPORTB |= portMask;
#endif
#endif // EI_SECTION_FALLING
#if defined EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifndef EI_NOTPORTB
#ifndef NEEDFORSPEED
calculatedPointer=&portBFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotB=*portInputRegister(portNumber);
pcmsk=&PCMSK0;
PCICR |= _BV(0);
#endif
#endif // EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifdef EI_SECTION_DISABLEPINCHANGE
#ifndef EI_NOTPORTB
PCMSK0 &= ~portMask;
if (PCMSK0 == 0) { PCICR &= ~_BV(0); };
risingPinsPORTB &= ~portMask;
fallingPinsPORTB &= ~portMask;
#endif
#endif // EI_SECTION_DISABLEPINCHANGE

عرض الملف

@@ -0,0 +1,69 @@
#ifdef EI_SECTION_RISING
#ifndef EI_NOTPORTA
if (portNumber==PA) {
risingPinsPORTA |= portMask;
}
#endif
#ifndef EI_NOTPORTB
if (portNumber==PB) {
risingPinsPORTB |= portMask;
}
#endif
#endif // EI_SECTION_RISING
#ifdef EI_SECTION_FALLING
#ifndef EI_NOTPORTA
if (portNumber==PA) {
fallingPinsPORTA |= portMask;
}
#endif
#ifndef EI_NOTPORTB
if (portNumber==PB) {
fallingPinsPORTB |= portMask;
}
#endif
#endif // EI_SECTION_FALLING
#if defined EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifndef EI_NOTPORTA
if (portNumber==PA) {
#ifndef NEEDFORSPEED
calculatedPointer=&portAFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotA=*portInputRegister(portNumber);
pcmsk=&PCMSK0;
GIMSK |= _BV(4);
}
#endif
#ifndef EI_NOTPORTB
if (portNumber==PB) {
#ifndef NEEDFORSPEED
calculatedPointer=&portBFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotB=*portInputRegister(portNumber);
pcmsk=&PCMSK1;
GIMSK |= _BV(5);
}
#endif
#endif // EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifdef EI_SECTION_DISABLEPINCHANGE
#ifndef EI_NOTPORTA
if (portNumber == PA) {
PCMSK0 &= ~portMask;
if (PCMSK0 == 0) { GIMSK &= ~_BV(4); };
risingPinsPORTA &= ~portMask;
fallingPinsPORTA &= ~portMask;
}
#endif
#ifndef EI_NOTPORTB
if (portNumber == PB) {
PCMSK1 &= ~portMask;
if (PCMSK1 == 0) { GIMSK &= ~_BV(5); };
risingPinsPORTB &= ~portMask;
fallingPinsPORTB &= ~portMask;
}
#endif
#endif // EI_SECTION_DISABLEPINCHANGE

عرض الملف

@@ -0,0 +1,32 @@
#ifdef EI_SECTION_RISING
#ifndef EI_NOTPORTB
risingPinsPORTB |= portMask;
#endif
#endif // EI_SECTION_RISING
#ifdef EI_SECTION_FALLING
#ifndef EI_NOTPORTB
fallingPinsPORTB |= portMask;
#endif
#endif // EI_SECTION_FALLING
#if defined EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifndef EI_NOTPORTB
#ifndef NEEDFORSPEED
calculatedPointer=&portBFunctions.pinZero + portBitNumber;
*calculatedPointer = userFunction;
#endif
portSnapshotB=*portInputRegister(portNumber);
pcmsk=&PCMSK;
GIMSK |= _BV(5);
#endif
#endif // EI_SECTION_ASSIGNFUNCTIONSREGISTERS
#ifdef EI_SECTION_DISABLEPINCHANGE
#ifndef EI_NOTPORTB
PCMSK &= ~portMask;
if (PCMSK == 0) { GIMSK &= ~_BV(5); };
risingPinsPORTB &= ~portMask;
fallingPinsPORTB &= ~portMask;
#endif
#endif // EI_SECTION_DISABLEPINCHANGE

عرض الملف

@@ -0,0 +1,137 @@
#ifdef INTERRUPT_FLAG_PIN0
volatile uint8_t INTERRUPT_FLAG_PIN0 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN1
volatile uint8_t INTERRUPT_FLAG_PIN1 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN2
volatile uint8_t INTERRUPT_FLAG_PIN2 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN3
volatile uint8_t INTERRUPT_FLAG_PIN3 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN4
volatile uint8_t INTERRUPT_FLAG_PIN4 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN5
volatile uint8_t INTERRUPT_FLAG_PIN5 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN6
volatile uint8_t INTERRUPT_FLAG_PIN6 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN7
volatile uint8_t INTERRUPT_FLAG_PIN7 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN8
volatile uint8_t INTERRUPT_FLAG_PIN8 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN9
volatile uint8_t INTERRUPT_FLAG_PIN9 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN10
volatile uint8_t INTERRUPT_FLAG_PIN10 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN11
volatile uint8_t INTERRUPT_FLAG_PIN11 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN12
volatile uint8_t INTERRUPT_FLAG_PIN12 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN13
volatile uint8_t INTERRUPT_FLAG_PIN13 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN14
volatile uint8_t INTERRUPT_FLAG_PIN14 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN15
volatile uint8_t INTERRUPT_FLAG_PIN15 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN18
volatile uint8_t INTERRUPT_FLAG_PIN18 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN19
volatile uint8_t INTERRUPT_FLAG_PIN19 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN20
volatile uint8_t INTERRUPT_FLAG_PIN20 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN21
volatile uint8_t INTERRUPT_FLAG_PIN21 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA0
volatile uint8_t INTERRUPT_FLAG_PINA0 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA1
volatile uint8_t INTERRUPT_FLAG_PINA1 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA2
volatile uint8_t INTERRUPT_FLAG_PINA2 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA3
volatile uint8_t INTERRUPT_FLAG_PINA3 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA4
volatile uint8_t INTERRUPT_FLAG_PINA4 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA5
volatile uint8_t INTERRUPT_FLAG_PINA5 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA8
volatile uint8_t INTERRUPT_FLAG_PINA8 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA9
volatile uint8_t INTERRUPT_FLAG_PINA9 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA10
volatile uint8_t INTERRUPT_FLAG_PINA10 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA11
volatile uint8_t INTERRUPT_FLAG_PINA11 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA12
volatile uint8_t INTERRUPT_FLAG_PINA12 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA13
volatile uint8_t INTERRUPT_FLAG_PINA13 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA14
volatile uint8_t INTERRUPT_FLAG_PINA14 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINA15
volatile uint8_t INTERRUPT_FLAG_PINA15 = 0;
#endif
#ifdef INTERRUPT_FLAG_PINSS
volatile uint8_t INTERRUPT_FLAG_PINSS = 0;
#endif
#ifdef INTERRUPT_FLAG_PINSCK
volatile uint8_t INTERRUPT_FLAG_PINSCK = 0;
#endif
#ifdef INTERRUPT_FLAG_PINMOSI
volatile uint8_t INTERRUPT_FLAG_PINMOSI = 0;
#endif
#ifdef INTERRUPT_FLAG_PINMISO
volatile uint8_t INTERRUPT_FLAG_PINMISO = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN70
volatile uint8_t INTERRUPT_FLAG_PIN70 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN71
volatile uint8_t INTERRUPT_FLAG_PIN71 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN72
volatile uint8_t INTERRUPT_FLAG_PIN72 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN73
volatile uint8_t INTERRUPT_FLAG_PIN73 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN74
volatile uint8_t INTERRUPT_FLAG_PIN74 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN75
volatile uint8_t INTERRUPT_FLAG_PIN75 = 0;
#endif
#ifdef INTERRUPT_FLAG_PIN76
volatile uint8_t INTERRUPT_FLAG_PIN76 = 0;
#endif

عرض الملف

@@ -0,0 +1,26 @@
#if defined MIGHTY1284
#ifdef INTERRUPT_FLAG_PIN24
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN24++;
#endif
#ifdef INTERRUPT_FLAG_PIN25
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN25++;
#endif
#ifdef INTERRUPT_FLAG_PIN26
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN26++;
#endif
#ifdef INTERRUPT_FLAG_PIN27
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN27++;
#endif
#ifdef INTERRUPT_FLAG_PIN28
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN28++;
#endif
#ifdef INTERRUPT_FLAG_PIN29
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN29++;
#endif
#ifdef INTERRUPT_FLAG_PIN30
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN30++;
#endif
#ifdef INTERRUPT_FLAG_PIN31
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN31++;
#endif
#endif

عرض الملف

@@ -0,0 +1,126 @@
#if defined ARDUINO_AVR_ENVIRODIY_MAYFLY || defined ARDUINO_AVR_SODAQ_MBILI
#if defined INTERRUPT_FLAG_PIN8
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN8++;
#endif
#if defined INTERRUPT_FLAG_PIN9
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN9++;
#endif
#if defined INTERRUPT_FLAG_PIN10
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN10++;
#endif
#if defined INTERRUPT_FLAG_PIN11
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN11++;
#endif
#if defined INTERRUPT_FLAG_PIN12
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN12++;
#endif
#if defined INTERRUPT_FLAG_PIN13
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN13++;
#endif
#if defined INTERRUPT_FLAG_PIN14
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN14++;
#endif
#if defined INTERRUPT_FLAG_PIN15
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN15++;
#endif
#elif defined MIGHTY1284
#ifdef INTERRUPT_FLAG_PIN0
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN0++;
#endif
#ifdef INTERRUPT_FLAG_PIN1
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN1++;
#endif
#ifdef INTERRUPT_FLAG_PIN2
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN2++;
#endif
#ifdef INTERRUPT_FLAG_PIN3
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN3++;
#endif
#ifdef INTERRUPT_FLAG_PIN4
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN4++;
#endif
#ifdef INTERRUPT_FLAG_PIN5
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN5++;
#endif
#ifdef INTERRUPT_FLAG_PIN6
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN6++;
#endif
#ifdef INTERRUPT_FLAG_PIN7
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN7++;
#endif
#endif
#if defined LEONARDO
#ifdef INTERRUPT_FLAG_PINSS
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PINSS++;
#endif
#ifdef INTERRUPT_FLAG_PINSCK
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PINSCK++;
#endif
#ifdef INTERRUPT_FLAG_PINMOSI
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PINMOSI++;
#endif
#ifdef INTERRUPT_FLAG_PINMISO
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PINMISO++;
#endif
#ifdef INTERRUPT_FLAG_PIN8
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN8++;
#endif
#ifdef INTERRUPT_FLAG_PIN9
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN9++;
#endif
#ifdef INTERRUPT_FLAG_PIN10
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN10++;
#endif
#ifdef INTERRUPT_FLAG_PIN11
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN11++;
#endif
#endif
#if defined ARDUINO_328
#ifdef INTERRUPT_FLAG_PIN8
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN8++;
#endif
#ifdef INTERRUPT_FLAG_PIN9
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN9++;
#endif
#ifdef INTERRUPT_FLAG_PIN10
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN10++;
#endif
#ifdef INTERRUPT_FLAG_PIN11
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN11++;
#endif
#ifdef INTERRUPT_FLAG_PIN12
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN12++;
#endif
#ifdef INTERRUPT_FLAG_PIN13
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN13++;
#endif
#endif
#if defined ARDUINO_MEGA
#ifdef INTERRUPT_FLAG_PINSS
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PINSS++;
#endif
#ifdef INTERRUPT_FLAG_PINSCK
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PINSCK++;
#endif
#ifdef INTERRUPT_FLAG_PINMOSI
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PINMOSI++;
#endif
#ifdef INTERRUPT_FLAG_PINMISO
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PINMISO++;
#endif
#ifdef INTERRUPT_FLAG_PIN10
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN10++;
#endif
#ifdef INTERRUPT_FLAG_PIN11
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN11++;
#endif
#ifdef INTERRUPT_FLAG_PIN12
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN12++;
#endif
#ifdef INTERRUPT_FLAG_PIN13
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN13++;
#endif
#endif

عرض الملف

@@ -0,0 +1,47 @@
#if defined MIGHTY1284
#if defined INTERRUPT_FLAG_PIN16
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN16++;
#endif
#if defined INTERRUPT_FLAG_PIN17
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN17++;
#endif
#if defined INTERRUPT_FLAG_PIN18
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN18++;
#endif
#if defined INTERRUPT_FLAG_PIN19
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN19++;
#endif
#if defined INTERRUPT_FLAG_PIN20
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN20++;
#endif
#if defined INTERRUPT_FLAG_PIN21
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN21++;
#endif
#if defined INTERRUPT_FLAG_PIN22
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN22++;
#endif
#if defined INTERRUPT_FLAG_PIN23
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN23++;
#endif
#endif
#if defined ARDUINO_328
#if defined INTERRUPT_FLAG_PINA0
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PINA0++;
#endif
#if defined INTERRUPT_FLAG_PINA1
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PINA1++;
#endif
#if defined INTERRUPT_FLAG_PINA2
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PINA2++;
#endif
#if defined INTERRUPT_FLAG_PINA3
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PINA3++;
#endif
#if defined INTERRUPT_FLAG_PINA4
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PINA4++;
#endif
#if defined INTERRUPT_FLAG_PINA5
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PINA5++;
#endif
#endif

عرض الملف

@@ -0,0 +1,78 @@
#if defined ARDUINO_AVR_ENVIRODIY_MAYFLY || defined ARDUINO_AVR_SODAQ_MBILI
#ifdef INTERRUPT_FLAG_PIN0
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN0++;
#endif
#ifdef INTERRUPT_FLAG_PIN1
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN1++;
#endif
#ifdef INTERRUPT_FLAG_PIN2
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN2++;
#endif
#ifdef INTERRUPT_FLAG_PIN3
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN3++;
#endif
#ifdef INTERRUPT_FLAG_PIN4
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN4++;
#endif
#ifdef INTERRUPT_FLAG_PIN5
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN5++;
#endif
#ifdef INTERRUPT_FLAG_PIN6
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN6++;
#endif
#ifdef INTERRUPT_FLAG_PIN7
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN7++;
#endif
#elif defined MIGHTY1284
#if defined INTERRUPT_FLAG_PIN8
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN8++;
#endif
#if defined INTERRUPT_FLAG_PIN9
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN9++;
#endif
#if defined INTERRUPT_FLAG_PIN10
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN10++;
#endif
#if defined INTERRUPT_FLAG_PIN11
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN11++;
#endif
#if defined INTERRUPT_FLAG_PIN12
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN12++;
#endif
#if defined INTERRUPT_FLAG_PIN13
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN13++;
#endif
#if defined INTERRUPT_FLAG_PIN14
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN14++;
#endif
#if defined INTERRUPT_FLAG_PIN15
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN15++;
#endif
#endif
#if defined ARDUINO_328
#if defined INTERRUPT_FLAG_PIN0
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN0++;
#endif
#if defined INTERRUPT_FLAG_PIN1
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN1++;
#endif
#if defined INTERRUPT_FLAG_PIN2
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN2++;
#endif
#if defined INTERRUPT_FLAG_PIN3
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN3++;
#endif
#if defined INTERRUPT_FLAG_PIN4
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN4++;
#endif
#if defined INTERRUPT_FLAG_PIN5
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN5++;
#endif
#if defined INTERRUPT_FLAG_PIN6
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN6++;
#endif
#if defined INTERRUPT_FLAG_PIN7
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PIN7++;
#endif
#endif

عرض الملف

@@ -0,0 +1,24 @@
#if defined ARDUINO_MEGA
#if defined INTERRUPT_FLAG_PIN15
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PIN15++;
#endif
#if defined INTERRUPT_FLAG_PIN14
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PIN14++;
#endif
#if defined INTERRUPT_FLAG_PIN70
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PIN70++;
#endif
#if defined INTERRUPT_FLAG_PIN71
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PIN71++;
#endif
#if defined INTERRUPT_FLAG_PIN72
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PIN72++;
#endif
#if defined INTERRUPT_FLAG_PIN73
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PIN73++;
#endif
#if defined INTERRUPT_FLAG_PIN74
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PIN74++;
#endif
#endif
// NOTE: 75 and 76 are "fake" External interrupt pins.

عرض الملف

@@ -0,0 +1,26 @@
#if defined ARDUINO_MEGA
#if defined INTERRUPT_FLAG_PINA8
if (interruptMask & _BV(0)) INTERRUPT_FLAG_PINA8++;
#endif
#if defined INTERRUPT_FLAG_PINA9
if (interruptMask & _BV(1)) INTERRUPT_FLAG_PINA9++;
#endif
#if defined INTERRUPT_FLAG_PINA10
if (interruptMask & _BV(2)) INTERRUPT_FLAG_PINA10++;
#endif
#if defined INTERRUPT_FLAG_PINA11
if (interruptMask & _BV(3)) INTERRUPT_FLAG_PINA11++;
#endif
#if defined INTERRUPT_FLAG_PINA12
if (interruptMask & _BV(4)) INTERRUPT_FLAG_PINA12++;
#endif
#if defined INTERRUPT_FLAG_PINA13
if (interruptMask & _BV(5)) INTERRUPT_FLAG_PINA13++;
#endif
#if defined INTERRUPT_FLAG_PINA14
if (interruptMask & _BV(6)) INTERRUPT_FLAG_PINA14++;
#endif
#if defined INTERRUPT_FLAG_PINA15
if (interruptMask & _BV(7)) INTERRUPT_FLAG_PINA15++;
#endif
#endif

224
libraries/PID/PID_v1.cpp Normal file
عرض الملف

@@ -0,0 +1,224 @@
/**********************************************************************************************
* Arduino PID Library - Version 1.1.1
* by Brett Beauregard <br3ttb@gmail.com> brettbeauregard.com
*
* This Library is licensed under a GPLv3 License
**********************************************************************************************/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <PID_v1.h>
/*Constructor (...)*********************************************************
* The parameters specified here are those for for which we can't set up
* reliable defaults, so we need to have the user set them.
***************************************************************************/
PID::PID(double* Input, double* Output, double* Setpoint,
double Kp, double Ki, double Kd, int POn, int ControllerDirection)
{
myOutput = Output;
myInput = Input;
mySetpoint = Setpoint;
inAuto = false;
PID::SetOutputLimits(0, 255); //default output limit corresponds to
//the arduino pwm limits
SampleTime = 100; //default Controller Sample Time is 0.1 seconds
PID::SetControllerDirection(ControllerDirection);
PID::SetTunings(Kp, Ki, Kd, POn);
lastTime = millis()-SampleTime;
}
/*Constructor (...)*********************************************************
* To allow backwards compatability for v1.1, or for people that just want
* to use Proportional on Error without explicitly saying so
***************************************************************************/
PID::PID(double* Input, double* Output, double* Setpoint,
double Kp, double Ki, double Kd, int ControllerDirection)
:PID::PID(Input, Output, Setpoint, Kp, Ki, Kd, P_ON_E, ControllerDirection)
{
}
/* Compute() **********************************************************************
* This, as they say, is where the magic happens. this function should be called
* every time "void loop()" executes. the function will decide for itself whether a new
* pid Output needs to be computed. returns true when the output is computed,
* false when nothing has been done.
**********************************************************************************/
bool PID::Compute()
{
if(!inAuto) return false;
unsigned long now = millis();
unsigned long timeChange = (now - lastTime);
if(timeChange>=SampleTime)
{
/*Compute all the working error variables*/
double input = *myInput;
double error = *mySetpoint - input;
double dInput = (input - lastInput);
outputSum+= (ki * error);
/*Add Proportional on Measurement, if P_ON_M is specified*/
if(!pOnE) outputSum-= kp * dInput;
if(outputSum > outMax) outputSum= outMax;
else if(outputSum < outMin) outputSum= outMin;
/*Add Proportional on Error, if P_ON_E is specified*/
double output;
if(pOnE) output = kp * error;
else output = 0;
/*Compute Rest of PID Output*/
output += outputSum - kd * dInput;
if(output > outMax) output = outMax;
else if(output < outMin) output = outMin;
*myOutput = output;
/*Remember some variables for next time*/
lastInput = input;
lastTime = now;
return true;
}
else return false;
}
/* SetTunings(...)*************************************************************
* This function allows the controller's dynamic performance to be adjusted.
* it's called automatically from the constructor, but tunings can also
* be adjusted on the fly during normal operation
******************************************************************************/
void PID::SetTunings(double Kp, double Ki, double Kd, int POn)
{
if (Kp<0 || Ki<0 || Kd<0) return;
pOn = POn;
pOnE = POn == P_ON_E;
dispKp = Kp; dispKi = Ki; dispKd = Kd;
double SampleTimeInSec = ((double)SampleTime)/1000;
kp = Kp;
ki = Ki * SampleTimeInSec;
kd = Kd / SampleTimeInSec;
if(controllerDirection ==REVERSE)
{
kp = (0 - kp);
ki = (0 - ki);
kd = (0 - kd);
}
}
/* SetTunings(...)*************************************************************
* Set Tunings using the last-rembered POn setting
******************************************************************************/
void PID::SetTunings(double Kp, double Ki, double Kd){
SetTunings(Kp, Ki, Kd, pOn);
}
/* SetSampleTime(...) *********************************************************
* sets the period, in Milliseconds, at which the calculation is performed
******************************************************************************/
void PID::SetSampleTime(int NewSampleTime)
{
if (NewSampleTime > 0)
{
double ratio = (double)NewSampleTime
/ (double)SampleTime;
ki *= ratio;
kd /= ratio;
SampleTime = (unsigned long)NewSampleTime;
}
}
/* SetOutputLimits(...)****************************************************
* This function will be used far more often than SetInputLimits. while
* the input to the controller will generally be in the 0-1023 range (which is
* the default already,) the output will be a little different. maybe they'll
* be doing a time window and will need 0-8000 or something. or maybe they'll
* want to clamp it from 0-125. who knows. at any rate, that can all be done
* here.
**************************************************************************/
void PID::SetOutputLimits(double Min, double Max)
{
if(Min >= Max) return;
outMin = Min;
outMax = Max;
if(inAuto)
{
if(*myOutput > outMax) *myOutput = outMax;
else if(*myOutput < outMin) *myOutput = outMin;
if(outputSum > outMax) outputSum= outMax;
else if(outputSum < outMin) outputSum= outMin;
}
}
/* SetMode(...)****************************************************************
* Allows the controller Mode to be set to manual (0) or Automatic (non-zero)
* when the transition from manual to auto occurs, the controller is
* automatically initialized
******************************************************************************/
void PID::SetMode(int Mode)
{
bool newAuto = (Mode == AUTOMATIC);
if(newAuto && !inAuto)
{ /*we just went from manual to auto*/
PID::Initialize();
}
inAuto = newAuto;
}
/* Initialize()****************************************************************
* does all the things that need to happen to ensure a bumpless transfer
* from manual to automatic mode.
******************************************************************************/
void PID::Initialize()
{
outputSum = *myOutput;
lastInput = *myInput;
if(outputSum > outMax) outputSum = outMax;
else if(outputSum < outMin) outputSum = outMin;
}
/* SetControllerDirection(...)*************************************************
* The PID will either be connected to a DIRECT acting process (+Output leads
* to +Input) or a REVERSE acting process(+Output leads to -Input.) we need to
* know which one, because otherwise we may increase the output when we should
* be decreasing. This is called from the constructor.
******************************************************************************/
void PID::SetControllerDirection(int Direction)
{
if(inAuto && Direction !=controllerDirection)
{
kp = (0 - kp);
ki = (0 - ki);
kd = (0 - kd);
}
controllerDirection = Direction;
}
/* Status Funcions*************************************************************
* Just because you set the Kp=-1 doesn't mean it actually happened. these
* functions query the internal state of the PID. they're here for display
* purposes. this are the functions the PID Front-end uses for example
******************************************************************************/
double PID::GetKp(){ return dispKp; }
double PID::GetKi(){ return dispKi;}
double PID::GetKd(){ return dispKd;}
int PID::GetMode(){ return inAuto ? AUTOMATIC : MANUAL;}
int PID::GetDirection(){ return controllerDirection;}

90
libraries/PID/PID_v1.h Normal file
عرض الملف

@@ -0,0 +1,90 @@
#ifndef PID_v1_h
#define PID_v1_h
#define LIBRARY_VERSION 1.1.1
class PID
{
public:
//Constants used in some of the functions below
#define AUTOMATIC 1
#define MANUAL 0
#define DIRECT 0
#define REVERSE 1
#define P_ON_M 0
#define P_ON_E 1
//commonly used functions **************************************************************************
PID(double*, double*, double*, // * constructor. links the PID to the Input, Output, and
double, double, double, int, int);// Setpoint. Initial tuning parameters are also set here.
// (overload for specifying proportional mode)
PID(double*, double*, double*, // * constructor. links the PID to the Input, Output, and
double, double, double, int); // Setpoint. Initial tuning parameters are also set here
void SetMode(int Mode); // * sets PID to either Manual (0) or Auto (non-0)
bool Compute(); // * performs the PID calculation. it should be
// called every time loop() cycles. ON/OFF and
// calculation frequency can be set using SetMode
// SetSampleTime respectively
void SetOutputLimits(double, double); // * clamps the output to a specific range. 0-255 by default, but
// it's likely the user will want to change this depending on
// the application
//available but not commonly used functions ********************************************************
void SetTunings(double, double, // * While most users will set the tunings once in the
double); // constructor, this function gives the user the option
// of changing tunings during runtime for Adaptive control
void SetTunings(double, double, // * overload for specifying proportional mode
double, int);
void SetControllerDirection(int); // * Sets the Direction, or "Action" of the controller. DIRECT
// means the output will increase when error is positive. REVERSE
// means the opposite. it's very unlikely that this will be needed
// once it is set in the constructor.
void SetSampleTime(int); // * sets the frequency, in Milliseconds, with which
// the PID calculation is performed. default is 100
//Display functions ****************************************************************
double GetKp(); // These functions query the pid for interal values.
double GetKi(); // they were created mainly for the pid front-end,
double GetKd(); // where it's important to know what is actually
int GetMode(); // inside the PID.
int GetDirection(); //
private:
void Initialize();
double dispKp; // * we'll hold on to the tuning parameters in user-entered
double dispKi; // format for display purposes
double dispKd; //
double kp; // * (P)roportional Tuning Parameter
double ki; // * (I)ntegral Tuning Parameter
double kd; // * (D)erivative Tuning Parameter
int controllerDirection;
int pOn;
double *myInput; // * Pointers to the Input, Output, and Setpoint variables
double *myOutput; // This creates a hard link between the variables and the
double *mySetpoint; // PID, freeing the user from having to constantly tell us
// what these values are. with pointers we'll just know.
unsigned long lastTime;
double outputSum, lastInput;
unsigned long SampleTime;
double outMin, outMax;
bool inAuto, pOnE;
};
#endif

11
libraries/PID/README.txt Normal file
عرض الملف

@@ -0,0 +1,11 @@
***************************************************************
* Arduino PID Library - Version 1.2.0
* by Brett Beauregard <br3ttb@gmail.com> brettbeauregard.com
*
* This Library is licensed under the MIT License
***************************************************************
- For an ultra-detailed explanation of why the code is the way it is, please visit:
http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/
- For function documentation see: http://playground.arduino.cc/Code/PIDLibrary

عرض الملف

@@ -0,0 +1,56 @@
/********************************************************
* PID Adaptive Tuning Example
* One of the benefits of the PID library is that you can
* change the tuning parameters at any time. this can be
* helpful if we want the controller to be agressive at some
* times, and conservative at others. in the example below
* we set the controller to use Conservative Tuning Parameters
* when we're near setpoint and more agressive Tuning
* Parameters when we're farther away.
********************************************************/
#include <PID_v1.h>
#define PIN_INPUT 0
#define PIN_OUTPUT 3
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Define the aggressive and conservative Tuning Parameters
double aggKp=4, aggKi=0.2, aggKd=1;
double consKp=1, consKi=0.05, consKd=0.25;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
void setup()
{
//initialize the variables we're linked to
Input = analogRead(PIN_INPUT);
Setpoint = 100;
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
void loop()
{
Input = analogRead(PIN_INPUT);
double gap = abs(Setpoint-Input); //distance away from setpoint
if (gap < 10)
{ //we're close to setpoint, use conservative tuning parameters
myPID.SetTunings(consKp, consKi, consKd);
}
else
{
//we're far from setpoint, use aggressive tuning parameters
myPID.SetTunings(aggKp, aggKi, aggKd);
}
myPID.Compute();
analogWrite(PIN_OUTPUT, Output);
}

عرض الملف

@@ -0,0 +1,35 @@
/********************************************************
* PID Basic Example
* Reading analog input 0 to control analog PWM output 3
********************************************************/
#include <PID_v1.h>
#define PIN_INPUT 0
#define PIN_OUTPUT 3
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
void setup()
{
//initialize the variables we're linked to
Input = analogRead(PIN_INPUT);
Setpoint = 100;
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
void loop()
{
Input = analogRead(PIN_INPUT);
myPID.Compute();
analogWrite(PIN_OUTPUT, Output);
}

عرض الملف

@@ -0,0 +1,36 @@
/********************************************************
* PID Proportional on measurement Example
* Setting the PID to use Proportional on measurement will
* make the output move more smoothly when the setpoint
* is changed. In addition, it can eliminate overshoot
* in certain processes like sous-vides.
********************************************************/
#include <PID_v1.h>
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1,P_ON_M, DIRECT); //P_ON_M specifies that Proportional on Measurement be used
//P_ON_E (Proportional on Error) is the default behavior
void setup()
{
//initialize the variables we're linked to
Input = analogRead(0);
Setpoint = 100;
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
void loop()
{
Input = analogRead(0);
myPID.Compute();
analogWrite(3,Output);
}

عرض الملف

@@ -0,0 +1,64 @@
/********************************************************
* PID RelayOutput Example
* Same as basic example, except that this time, the output
* is going to a digital pin which (we presume) is controlling
* a relay. the pid is designed to Output an analog value,
* but the relay can only be On/Off.
*
* to connect them together we use "time proportioning
* control" it's essentially a really slow version of PWM.
* first we decide on a window size (5000mS say.) we then
* set the pid to adjust its output between 0 and that window
* size. lastly, we add some logic that translates the PID
* output into "Relay On Time" with the remainder of the
* window being "Relay Off Time"
********************************************************/
#include <PID_v1.h>
#define PIN_INPUT 0
#define RELAY_PIN 6
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
int WindowSize = 5000;
unsigned long windowStartTime;
void setup()
{
windowStartTime = millis();
//initialize the variables we're linked to
Setpoint = 100;
//tell the PID to range between 0 and the full window size
myPID.SetOutputLimits(0, WindowSize);
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
void loop()
{
Input = analogRead(PIN_INPUT);
myPID.Compute();
/************************************************
* turn the output pin on/off based on pid output
************************************************/
if (millis() - windowStartTime > WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if (Output < millis() - windowStartTime) digitalWrite(RELAY_PIN, HIGH);
else digitalWrite(RELAY_PIN, LOW);
}

عرض الملف

@@ -0,0 +1,36 @@
#######################################
# Syntax Coloring Map For PID Library
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
PID KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
SetMode KEYWORD2
Compute KEYWORD2
SetOutputLimits KEYWORD2
SetTunings KEYWORD2
SetControllerDirection KEYWORD2
SetSampleTime KEYWORD2
GetKp KEYWORD2
GetKi KEYWORD2
GetKd KEYWORD2
GetMode KEYWORD2
GetDirection KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
AUTOMATIC LITERAL1
MANUAL LITERAL1
DIRECT LITERAL1
REVERSE LITERAL1
P_ON_E LITERAL1
P_ON_M LITERAL1

عرض الملف

@@ -0,0 +1,19 @@
{
"name": "PID",
"keywords": "PID, controller, signal",
"description": "A PID controller seeks to keep some input variable close to a desired setpoint by adjusting an output. The way in which it does this can be 'tuned' by adjusting three parameters (P,I,D).",
"url": "http://playground.arduino.cc/Code/PIDLibrary",
"include": "PID_v1",
"authors":
[
{
"name": "Brett Beauregard"
}
],
"repository":
{
"type": "git",
"url": "https://github.com/br3ttb/Arduino-PID-Library.git"
},
"frameworks": "arduino"
}

عرض الملف

@@ -0,0 +1,9 @@
name=PID
version=1.2.0
author=Brett Beauregard
maintainer=Brett Beauregard
sentence=PID controller
paragraph=A PID controller seeks to keep some input variable close to a desired setpoint by adjusting an output. The way in which it does this can be 'tuned' by adjusting three parameters (P,I,D).
category=Signal Input/Output
url=http://playground.arduino.cc/Code/PIDLibrary
architectures=*

عرض الملف

@@ -0,0 +1,28 @@
Copyright (c) 2015, Mark Rose
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of bsd-license nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

عرض الملف

@@ -0,0 +1,93 @@
= SimplePID
A PID controller library independent of run environment, but one which works well with Arduino.
== Installation
To install the library into your Arduino installation, go to the _Releases_ tab and download
the latest release. This will be a ZIP file called `SimplePID-__version__.zip`, for some
version number. Unzip this into your `__sketchbook__/libraries` folder, where _sketchbook_
is the root of your Arduino sketches. On OS X and Windows it is usually `~/Documents/Arduino`.
This will create a directory called `SimplePID-__version__`. Rename that directory to
`SimplePID`.
You should then have a directory under your _sketchbook_ directory containing the library files at:
libraries/SimplePID/
== Usage
To use the SimplePID library, add `#include <SimplePID.h>` to the includes in your sketch.
Then create an instance of the PID controller by defining a global variable:
----
SimplePID myPID(pConstant, iConstant, dConstant);
----
(Replace `pConstant`, `iConstant`, and `dConstant` with the proportional, integral, and differential
constants you desire.) For a P-controller, set the integral and differential constants to zero,
for example.
=== Setting the Target
The target value you want to track is usually called the _setpoint_. At any time you can change
the setpoint by calling `SimplePID.setSetPoint(someValue)`. For example, using the PID controller
defined in the example above, we could set the target at 3.4 as follows:
----
myPID.setSetPoint(3.4);
----
=== Getting the Control Value
Your code needs to have some way of keeping track of time in order to determine the delta
time from the last control value. A recommended way of doing that is farther down. You also
need to have a way of sensing the actual error value,
the difference in speed of the motor versus the desired value, or the process error.
Once you have the actual error value and the delta time, in seconds, you get the control value
to use like this:
----
float controlValue = myPID.getControlValue(actualError, dt);
----
For a motor, you will usually add the control value to the current control value and change
the motor speed.
=== Keeping Track of Delta Time
One way of doing that is as follows:
----
#include <SimplePID.h>
SimplePID myPID(...);
unsigned long lastLoopTime;
void setup() {
...
lastLoopTime = micros();
}
void loop() {
delay(howeverLongYouLike);
float error = ... some way of getting the actual error value ...
unsigned long curLoopTime = micros();
float dt = (curLoopTime - lastLoopTime) / 1E6;
float controlValue = myPID.getControlValue(error, dt);
... code to control the motor or other process ...
lastLoopTime = curLoopTime;
}
----
In this case `dt` is set to the delta time since the last control, in seconds.
== An Example
There is an example of using the library to investigate PID tunings for a motor. It is specific
to the DFRobot Romeo v2 Arduino board and motor driver, but should give a reasonable impression
of how to use `SimplePID`. Open that sketch by going to Files > Examples > SimplePID > RomeoPIDTest.

عرض الملف

@@ -0,0 +1,61 @@
#include <float.h>
#include "SimplePID.h"
SimplePID::SimplePID(float Kp, float Ki, float Kd) {
this->Kp = Kp;
this->Ki = Ki;
this->Kd = Kd;
minOutput = -FLT_MAX;
maxOutput = FLT_MAX;
sumError = 0.0;
lastActual = 0.0;
}
void SimplePID::setConstants(float Kp, float Ki, float Kd) {
this->Kp = Kp;
this->Ki = Ki;
this->Kd = Kd;
}
void SimplePID::setOutputRange(float minOutput, float maxOutput) {
this->minOutput = minOutput;
this->maxOutput = maxOutput;
}
void SimplePID::setSetPoint(float setPoint) {
this->setPoint = setPoint;
sumError = 0.0;
}
float SimplePID::getCumulativeError() {
return sumError;
}
void SimplePID::clearCumulativeError() {
sumError = 0.0;
}
float SimplePID::getControlValue(float actual, float dt) {
float error = setPoint - actual;
float newSum = sumError + error*dt;
// The derivative is calculated by assuming the two setpoints are
// equal. This works better when changing the setpoint because the
// derivative error does not suddenly increase.
float dErrorDt = (lastActual - actual) / dt;
lastActual = actual;
float output = Kp*error + Ki*sumError + Kd*dErrorDt;
if (output >= maxOutput) {
return maxOutput;
} else if (output <= minOutput) {
return minOutput;
} else {
sumError = newSum;
return output;
}
}

عرض الملف

@@ -0,0 +1,36 @@
// SimplePID.h - Definitions for the simple PID library.
#ifndef SIMPLE_PID_H
#define SIMPLE_PID_H
class SimplePID {
public:
SimplePID(float Kp, float Ki, float Kd);
void setConstants(float Kp, float Ki, float Kd);
void setOutputRange(float minOutput, float maxOutput);
void setSetPoint(float setPoint);
float getCumulativeError();
void clearCumulativeError();
float getControlValue(float actual, float dt);
private:
float Kp;
float Ki;
float Kd;
float setPoint;
float minOutput;
float maxOutput;
float lastActual;
float sumError;
};
#endif SIMPLE_PID_H

عرض الملف

@@ -0,0 +1,296 @@
// AStarPIDTest - Test the PID control for an AStar-based robot.
//
// To gather PID tuning data for graphing, put the robot on blocks, then
// start this program and open a Serial Monitor. Press S4 to start both
// motors, let them come to a steady speed, then press S4 to stop the
// motors. Copy the Serial output to a spreadsheet and plot target speed and
// current speed versus time. You should see a classic PID controller graph
// with some overshoot.
#include <AStar32U4.h>
#include <EnableInterrupt.h>
#include <SimplePID.h>
// Motor parameters. These are based on a Pololu #2285 motor with 48cpr
// encoder.
const float GEAR_RATIO = 210.59;
const float ENCODER_CPR = 12;
// Number of encoder ticks per revolution of the wheel.
const float TICKS_PER_REV = GEAR_RATIO * ENCODER_CPR;
// Maximum desired motor speed. Pololu #2285 are rated for 130rpm, but we
// don't drive them with enough voltage to achieve that.
const float MAX_REVS_PER_SEC = 100.0 / 60.0;
// Use 60% of maximum speed for PID tuning.
const int PID_TUNING_TICKS_PER_SEC = 0.6 * MAX_REVS_PER_SEC * TICKS_PER_REV;
// DFRobot Romeo v2 and BLE PIN assignments.
const int ONBOARD_SWITCH_PIN = A7;
// Pins for the Pololu motor encoder outputs.
const int M1_A = 7;
const int M1_B = 11;
const int M2_A = 15;
const int M2_B = 16;
// Minimum motor control value. Motor output below this will stall.
const int MIN_MOTOR_CMD = 10;
// Maximum motor control value.
const int MAX_MOTOR_CMD = 400;
AStar32U4Motors motors;
// These objects provide access to the A-Star's on-board
// buttons. We will only use buttonA.
AStar32U4ButtonA buttonA;
AStar32U4ButtonB buttonB;
AStar32U4ButtonC buttonC;
enum { NO_BUTTON, BUTTON_A, BUTTON_B, BUTTON_C };
int leftSpeedTarget = 0;
int rightSpeedTarget = 0;
volatile long leftTicks;
volatile long rightTicks;
long lastLeftTicks = 0;
long lastRightTicks = 0;
int leftMotorCmd = 0;
int rightMotorCmd = 0;
unsigned long lastLoopTime;
unsigned long lastSwitchTime;
float loopTime = 0.0;
// Ziegler-Nichols tuning. See this Wikipedia article for details:
// https://en.wikipedia.org/wiki/PID_controller#Loop_tuning
// To tune the controller, set USE_KU_ONLY to 1 and increase Ku
// until oscillation occurs, and set Tu to the oscillation period
// in seconds. Then set USE_KU_ONLY to zero to use the
// Ziegler-Nichols tune. To get a less agressive tune, set LESS_AGGRESSIVE
// to 1.
// Set to 1 to use Ku only, to determine oscillation point.
#define USE_KU_ONLY 0
const float Ku = .15;
const float Tu = .1142857143;
#define MANUAL_TUNE 1
#define LESS_AGGRESSIVE 0
#if MANUAL_TUNE
// Found empirically to rapidly converge with little overshoot.
// There is no integral constant, but not needed when driving
// on flat ground, and when the heading is otherwise controlled
// by higher-level software. (I.e., there's no need to catch up
// for past errors.)
const float Kp = 0.07;
const float Ki = 0.0;
const float Kd = 0.001;
#elif !LESS_AGGRESSIVE
const float Kp = 0.6*Ku;
const float Ki = 2*Kp/Tu;
const float Kd = Kp*Tu/8;
#else
const float Kp = 0.2*Ku;
const float Ki = 2*Kp/Tu;
const float Kd = Kp*Tu/3;
#endif
#if USE_KU_ONLY
SimplePID leftController = SimplePID(Ku, 0, 0);
SimplePID rightController = SimplePID(Ku, 0, 0);
#else
SimplePID leftController = SimplePID(Kp, Ki, Kd);
SimplePID rightController = SimplePID(Kp, Ki, Kd);
#endif
// Sets up the serial output and the motor control pins, and attaches
// interrupt handlers to the pins on which we will read the encoder
// phototransistor values.
void setup() {
Serial.begin(115200);
delay(3000);
enableInterrupt(M1_A, leftAChange, CHANGE);
enableInterrupt(M1_B, leftBChange, CHANGE);
enableInterrupt(M2_A, rightAChange, CHANGE);
enableInterrupt(M2_B, rightBChange, CHANGE);
// Serial.print("Time (s)\t");
Serial.print("Left Target\tLeft Speed");
// Serial.print("\tLeft Cum Error\tLeft Motor\t");
Serial.print("\tRight Target\tRight Speed");
// Serial.print("\tRight Cum Error\tRight Motor");
Serial.println();
lastLoopTime = micros();
lastSwitchTime = millis();
leftTicks = rightTicks = 0;
}
// Loops forever showing the motor speeds and errors since the last loop,
// and adjusts the target speeds depending on whether the user is pressing
// switches S2 through S5, as indicated in the code below.
void loop() {
delay(15);
unsigned long curLoopTime = micros();
noInterrupts();
long curLeftTicks = leftTicks;
long curRightTicks = rightTicks;
interrupts();
float dt = (curLoopTime - lastLoopTime) / 1E6;
float leftSpeed = (curLeftTicks - lastLeftTicks) / dt;
float rightSpeed = (curRightTicks - lastRightTicks) / dt;
int leftControl = leftController.getControlValue(leftSpeed, dt);
leftMotorCmd += min(MAX_MOTOR_CMD, leftControl);
leftMotorCmd = constrain(leftMotorCmd, -MAX_MOTOR_CMD, MAX_MOTOR_CMD);
if (leftMotorCmd > 0) {
leftMotorCmd = max(leftMotorCmd, MIN_MOTOR_CMD);
}
int rightControl = rightController.getControlValue(rightSpeed, dt);
rightMotorCmd += min(MAX_MOTOR_CMD, rightControl);
rightMotorCmd = constrain(rightMotorCmd, -MAX_MOTOR_CMD, MAX_MOTOR_CMD);
if (rightMotorCmd > 0) {
rightMotorCmd = max(rightMotorCmd, MIN_MOTOR_CMD);
}
// Coast to a stop if target is zero.
if (leftSpeedTarget == 0) {
leftMotorCmd = 0;
}
if (rightSpeedTarget == 0) {
rightMotorCmd = 0;
}
setSpeed(leftMotorCmd, rightMotorCmd);
if (leftSpeedTarget > 0 || leftSpeed > 0 || rightSpeedTarget > 0 || rightSpeed > 0) {
// Serial.print(loopTime, 3);
// Serial.print("\t");
Serial.print(leftSpeedTarget);
Serial.print("\t");
Serial.print(leftSpeed);
Serial.print("\t");
// Serial.print(leftController.getCumulativeError());
// Serial.print("\t");
// Serial.print(leftMotorCmd);
// Serial.print("\t");
Serial.print(rightSpeedTarget);
Serial.print("\t");
Serial.print(rightSpeed);
Serial.print("\t");
// Serial.print(rightController.getCumulativeError());
// Serial.print("\t");
// Serial.print(rightMotorCmd);
// Serial.print("\t");
Serial.println();
loopTime += dt;
}
// Ignore switches for a short time after pressing, to avoid bounce.
if (curLoopTime - lastSwitchTime > 0.5*1E6) {
int switchValue = readSwitch();
if (switchValue > 0) {
lastSwitchTime = curLoopTime;
switch (switchValue) {
case BUTTON_A:
// Left motor on/off.
leftSpeedTarget = (leftSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
break;
case BUTTON_B:
// Right motor on/off.
rightSpeedTarget = (rightSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
break;
case BUTTON_C:
// Both motors on/off.
leftSpeedTarget = (leftSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
rightSpeedTarget = (rightSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
break;
default:
// no change in speed
break;
}
leftController.setSetPoint(leftSpeedTarget);
rightController.setSetPoint(rightSpeedTarget);
}
}
lastLeftTicks = curLeftTicks;
lastRightTicks = curRightTicks;
lastLoopTime = curLoopTime;
}
void waitForSwitch1() {
while (readSwitch() != 1) {
// do nothing
}
}
void setSpeed(int leftSpeed, int rightSpeed) {
motors.setSpeeds(leftSpeed, rightSpeed);
}
void leftAChange() {
if (digitalRead(M1_A) == digitalRead(M1_B)) {
++leftTicks;
} else {
--leftTicks;
}
}
void leftBChange() {
if (digitalRead(M1_A) != digitalRead(M1_B)) {
++leftTicks;
} else {
--leftTicks;
}
}
void rightAChange() {
if (digitalRead(M2_A) != digitalRead(M2_B)) {
++rightTicks;
} else {
--rightTicks;
}
}
void rightBChange() {
if (digitalRead(M2_A) == digitalRead(M2_B)) {
++rightTicks;
} else {
--rightTicks;
}
}
int readSwitch() {
if (buttonA.getSingleDebouncedRelease()) {
return BUTTON_A;
} else if (buttonB.getSingleDebouncedRelease()) {
return BUTTON_B;
} else if (buttonC.getSingleDebouncedRelease()) {
return BUTTON_C;
} else {
return 0;
}
}

عرض الملف

@@ -0,0 +1,294 @@
// RomeoPIDTest - Test the PID control for a DFRobot Romeo-based robot.
//
// To gather PID tuning data for graphing, put the robot on blocks, then
// start this program and open a Serial Monitor. Press S4 to start both
// motors, let them come to a steady speed, then press S4 to stop the
// motors. Copy the Serial output to a spreadsheet and plot target speed and
// current speed versus time. You should see a classic PID controller graph
// with some overshoot.
#include <EnableInterrupt.h>
#include <SimplePID.h>
// Motor parameters. These are based on a Pololu #2285 motor with 48cpr
// encoder.
const float GEAR_RATIO = 46.85;
const float ENCODER_CPR = 48;
// Number of encoder ticks per revolution of the wheel.
const float TICKS_PER_REV = GEAR_RATIO * ENCODER_CPR;
// Maximum desired motor speed. Pololu #2285 are rated for 130rpm, but we
// don't drive them with enough voltage to achieve that.
const float MAX_REVS_PER_SEC = 100.0 / 60.0;
// Use 60% of maximum speed for PID tuning.
const int PID_TUNING_TICKS_PER_SEC = 0.6 * MAX_REVS_PER_SEC * TICKS_PER_REV;
// DFRobot Romeo v2 and BLE PIN assignments.
const int ONBOARD_SWITCH_PIN = A0;
const int LEFT_DIRECTION = 4;
const int LEFT_SPEED = 5;
const int RIGHT_SPEED = 6;
const int RIGHT_DIRECTION = 7;
// Pins for the Pololu motor encoder outputs.
const int M1_A = 10;
const int M1_B = 11;
const int M2_A = 14;
const int M2_B = 15;
// Minimum motor control value. Motor output below this will stall.
const int MIN_MOTOR_CMD = 60;
int leftSpeedTarget = 0;
int rightSpeedTarget = 0;
volatile unsigned long leftTicks = 0;
volatile unsigned long lastLeftTickTime = 0;
volatile unsigned long rightTicks = 0;
volatile unsigned long lastRightTickTime = 0;
int lastLeftTicks = 0;
int lastRightTicks = 0;
int leftMotorCmd = 0;
int rightMotorCmd = 0;
unsigned long lastLoopTime;
unsigned long lastSwitchTime;
float loopTime = 0.0;
// Ziegler-Nichols tuning. See this Wikipedia article for details:
// https://en.wikipedia.org/wiki/PID_controller#Loop_tuning
// To tune the controller, set USE_KU_ONLY to 1 and increase Ku
// until oscillation occurs, and set Tu to the oscillation period
// in seconds. Then set USE_KU_ONLY to zero to use the
// Ziegler-Nichols tune. To get a less agressive tune, set LESS_AGGRESSIVE
// to 1.
// Set to 1 to use Ku only, to determine oscillation point.
#define USE_KU_ONLY 0
const float Ku = .11;
const float Tu = .20;
#define LESS_AGGRESSIVE 0
#if !LESS_AGGRESSIVE
const float Kp = 0.6*Ku;
const float Ki = 2*Kp/Tu;
const float Kd = Kp*Tu/8;
#else
const float Kp = 0.2*Ku;
const float Ki = 2*Kp/Tu;
const float Kd = Kp*Tu/3;
#endif
#if USE_KU_ONLY
SimplePID leftController = SimplePID(Ku, 0, 0);
SimplePID rightController = SimplePID(Ku, 0, 0);
#else
SimplePID leftController = SimplePID(Kp, Ki, Kd);
SimplePID rightController = SimplePID(Kp, Ki, Kd);
#endif
// Sets up the serial output and the motor control pins, and attaches
// interrupt handlers to the pins on which we will read the encoder
// phototransistor values.
void setup() {
Serial.begin(115200);
delay(3000);
pinMode(LEFT_DIRECTION, OUTPUT);
pinMode(LEFT_SPEED, OUTPUT);
pinMode(RIGHT_DIRECTION, OUTPUT);
pinMode(RIGHT_SPEED, OUTPUT);
enableInterrupt(M1_A, leftAChange, CHANGE);
enableInterrupt(M1_B, leftBChange, CHANGE);
enableInterrupt(M2_A, rightAChange, CHANGE);
enableInterrupt(M2_B, rightBChange, CHANGE);
Serial.print("Time (s)\tLeft Target\tLeft Speed\tLeft Cum Error\tLeft Motor");
Serial.print("\tRight Target\tRight Speed\tRight Cum Error\tRight Motor");
Serial.println();
lastLoopTime = micros();
lastSwitchTime = millis();
}
// Loops forever showing the motor speeds and errors since the last loop,
// and adjusts the target speeds depending on whether the user is pressing
// switches S2 through S5, as indicated in the code below.
void loop() {
delay(15);
unsigned long curLoopTime = micros();
noInterrupts();
int curLeftTicks = leftTicks;
int curRightTicks = rightTicks;
interrupts();
float dt = (curLoopTime - lastLoopTime) / 1E6;
float leftSpeed = (curLeftTicks - lastLeftTicks) / dt;
float rightSpeed = (curRightTicks - lastRightTicks) / dt;
int leftControl = leftController.getControlValue(leftSpeed, dt);
leftMotorCmd += min(255, leftControl);
leftMotorCmd = constrain(leftMotorCmd, -255, 255);
if (leftMotorCmd > 0) {
leftMotorCmd = max(leftMotorCmd, MIN_MOTOR_CMD);
}
int rightControl = rightController.getControlValue(rightSpeed, dt);
rightMotorCmd += min(255, rightControl);
rightMotorCmd = constrain(rightMotorCmd, -255, 255);
if (rightMotorCmd > 0) {
rightMotorCmd = max(rightMotorCmd, MIN_MOTOR_CMD);
}
// Coast to a stop if target is zero.
if (leftSpeedTarget == 0) {
leftMotorCmd = 0;
}
if (rightSpeedTarget == 0) {
rightMotorCmd = 0;
}
setSpeed(leftMotorCmd, rightMotorCmd);
if (leftSpeedTarget > 0 || leftSpeed > 0 || rightSpeedTarget > 0 || rightSpeed > 0) {
Serial.print(loopTime, 3);
Serial.print("\t");
Serial.print(leftSpeedTarget);
Serial.print("\t");
Serial.print(leftSpeed);
Serial.print("\t");
Serial.print(leftController.getCumulativeError());
Serial.print("\t");
Serial.print(leftMotorCmd);
Serial.print("\t");
Serial.print(rightSpeedTarget);
Serial.print("\t");
Serial.print(rightSpeed);
Serial.print("\t");
Serial.print(rightController.getCumulativeError());
Serial.print("\t");
Serial.print(rightMotorCmd);
Serial.print("\t");
Serial.println();
loopTime += dt;
}
// Ignore switches for a short time after pressing, to avoid bounce.
if (curLoopTime - lastSwitchTime > 0.5*1E6) {
int switchValue = readSwitch();
if (switchValue > 0) {
lastSwitchTime = curLoopTime;
switch (switchValue) {
case 2:
// Left motor on/off.
leftSpeedTarget = (leftSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
break;
case 3:
// Right motor on/off.
rightSpeedTarget = (rightSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
break;
case 4:
// Both motors on/off.
leftSpeedTarget = (leftSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
rightSpeedTarget = (rightSpeedTarget==0 ? PID_TUNING_TICKS_PER_SEC : 0);
break;
case 5:
break;
default:
// no change in speed
break;
}
leftController.setSetPoint(leftSpeedTarget);
rightController.setSetPoint(rightSpeedTarget);
}
}
lastLeftTicks = curLeftTicks;
lastRightTicks = curRightTicks;
lastLoopTime = curLoopTime;
}
void waitForSwitch1() {
while (readSwitch() != 1) {
// do nothing
}
}
void setSpeed(int leftSpeed, int rightSpeed) {
digitalWrite(LEFT_DIRECTION, (leftSpeed >= 0 ? HIGH : LOW));
analogWrite(LEFT_SPEED, abs(leftSpeed));
digitalWrite(RIGHT_DIRECTION, (rightSpeed >= 0 ? HIGH : LOW));
analogWrite(RIGHT_SPEED, abs(rightSpeed));
}
void leftAChange() {
if (digitalRead(M1_A) == digitalRead(M1_B)) {
++leftTicks;
} else {
--leftTicks;
}
}
void leftBChange() {
if (digitalRead(M1_A) != digitalRead(M1_B)) {
++leftTicks;
} else {
--leftTicks;
}
}
void rightAChange() {
if (digitalRead(M2_A) != digitalRead(M2_B)) {
++rightTicks;
} else {
--rightTicks;
}
}
void rightBChange() {
if (digitalRead(M2_A) == digitalRead(M2_B)) {
++rightTicks;
} else {
--rightTicks;
}
}
// Reads the value of the built-in switches S1 through S5. The switches
// are connected in parallel with resistors of five different sizes to
// analog pin A0. The difference in voltage at A0 allows us to determine
// which switch is pressed.
int readSwitch() {
int value = analogRead(ONBOARD_SWITCH_PIN);
if (value > 800) {
return 0;
} else if (value > 600) {
return 5;
} else if (value > 400) {
return 4;
} else if (value > 250) {
return 3;
} else if (value > 75) {
return 2;
} else {
return 1;
}
}