Develop a program for the ATmega328 microcontroller of the Arduino Nano debugging board - arduino

It is necessary to realize the function of an auto-oscillating multivibrator with one output. The frequency of rectangular pulses is f-10 kHz, the duration of the current signal pulse is 36 µs. Every 20 ms interrogate the button with a timer and if the button is pressed the pulses are switched off and if the button is not pressed the oscillator is switched on again.
uint16_t x = 10000;
float y = 36.0;
void setup() {
Serial.begin(115200);
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
OCR1A = ((float) y / 0.0625 ) // or OCR1A = (F_CPU/x) / 4; ???
ICR1 = (F_CPU/x)-1;
}
void loop() {
}
Then my fantasy ended

Related

Arduino Interfacing with Magnetic Pickup

Currently I have a diesel engine with magnetic pickup attached to it. I want to use Arduino (Uno/Nano) to measure engine RPM.
Magnetic Pickup Description: A magnetic pickup is installed over a gear, (most commonly the flywheel inside a vehicle’s bell housing) and as the gear turns the pickup will create an electric pulse for each tooth on the gear. These pulses are then read by the instrument which interprets it to indicate the correct RPMs or speed.The signal from the magnetic speed Sensor, teeth per second(HZ), is directly proportional to engine speed.
Magnetic Pickup Image:
MP - Self Powered
I've tried to rectify the signal using diode then limit the current using a resistor with .1Uf capacitor to filter the noise, then connected it to Optocopler 4N35 and the output from Opto to Arduino interrupt pin, by just observing Arduino interrupt ping is highly affected by surroundings.
Also I have tried to directly connect the magnetic pickup to "A0" pin and use analogue read and connect a led to pin 13 just to monitor the pulses from MP.
int sensorPin = A0;
int ledPin = 13;
int sensorValue = 0;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
digitalWrite(ledPin, HIGH);
delay(sensorValue);
digitalWrite(ledPin, LOW);
Serial.println(sensorValue);
Serial.println(" ");
}
Using analogueRead works with the LED as indicator for pulses generated by pickup. (Tested using small motor and small gear to protect Arduino).
Also I tried to use LM139 Comparator but the readings make no sense
(ex: 60 RPM, 1500 RPM,2150 RPM, 7150 RPM).
LM139 Circuit
Code used with LM139:
// read RPM
volatile int rpmcount = 0;
//see http://arduino.cc/en/Reference/Volatile
int rpm = 0;
unsigned long lastmillis = 0;
void setup() {
Serial.begin(9600);
attachInterrupt(0, rpm_fan, RISING);
//interrupt cero (0) is on pin two(2).
}
void loop() {
if (millis() - lastmillis == 500) {
/*Update every one second, this will be equal to reading frequency (Hz).*/
detachInterrupt(0); //Disable interrupt when calculating
rpm = rpmcount * 60;
/* Convert frequency to RPM, note: this works for one interruption per full rotation. For two interrupts per full rotation use rpmcount * 30.*/
Serial.print(rpm); // print the rpm value.
Serial.println(" ");
rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Update lastmillis
attachInterrupt(0, rpm_fan, RISING); //enable interrupt
}
}
void rpm_fan() {
/* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmcount++;
}
// Elimelec Lopez - April 25th 2013
What is the best way or approach to interface a magnetic pickup with Arduino to display RPM?
Your use of analogRead is wrong. Besides, analogRead will not get you anywhere close to what you want to achieve.
What you want from your pickup is a clear 0-5v digital signal. You can obtain that by playing with the input resistor on your opto-coupler. I'd do some measurements, and place a trimpot + resistors on the board do the actual value can be tweaked after the system is installed.
Once you get the electrical signal as clean as you can get, you can the use an interrupt pin on the Arduino to keep count of the number of pulses.
#define SENSOR_PIN (2) // using define instead of variable for constants save memory.
#define LED_PIN (13)
#define READ_DELAY (100) // in milliseconds.
// we'll get a reading every 100ms, so 8 bits are enough to keep
// track of time. You'd have to widen to unsigned int if you want
// READ_DELAY to exceed 255 ms.
//
typedef delay_type unsigned char;
typedef unsigned int counter_type; // You may want to use
// unsigned long, if you
// experience overflows.
volatile counter_type pulseCount = 0; // volatile is important here
counter_type lastCount = 0;
delay_type lastTime = 0;
// pulse interrupt callback, keep short.
void onSensorPulse()
{
++pulseCount;
// the following may already be too long. Use for debugging only
// digitalWrite() and digitalRead() are notoriously slow.
//
//
// digitalWrite(LED_PIN, !digitalRead(LED_PIN));
//
// using fastest direct port access instead. (for ATMega)
//
if (pulseCount & 1)
PORTB |= (1 << PB5);
else
PORTB &= ~(1 << PB5);
}
void setup()
{
pinMode(SENSOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), onSensorPulse, RISING);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
// control frequency of readings
//
delay_type now = (delay_type)millis();
if (now - lastTime < READ_DELAY)
{
return;
}
lastTime = now;
// get a reading. must disable interrupts while doing so.
// because pulseCount is multi-bytes.
//
noInterrupts();
counter_type curCount = pulseCount;
interrupts();
// get the number of pulses since last reading.
//
counter_type delta = curCount - lastCount;
lastCount = curCount;
// to convert to RPMs, you will need to use this formula:
// note the use of long (UL) to avoid overflows in the
// computation. 60000 = miliseconds per minute.
//
// RPM = delta * 60000UL / (READ_DELAY * TEETH_COUNT);
// send delta to client for now.
//
Serial.println(delta);
}

Arduino Button with LED

I have put together an Arduino circuit that turns the led's off when the button is pressed. How do I code it so when I press it once it comes on and stays on and will only turn off once its pressed again? Any help would be appreciated
My Current code is:
int ledred = 12;
int ledgreen = 8;
int BUTTON = 4;
int speakerPin = 1;
void setup() {
// initialize the digital pin as an output.
Serial.begin(9600);
pinMode(ledgreen, OUTPUT);
pinMode(ledred, OUTPUT);
pinMode(BUTTON,INPUT);
}
void loop() {
if(digitalRead(BUTTON) == HIGH){
digitalWrite(ledred,HIGH);
digitalWrite(ledgreen,HIGH);
}else
{
digitalWrite(ledred,LOW);
digitalWrite(ledgreen,LOW);
}
}
If all you want is do this, you can use one of the interrupt pins and watch for the RISING (or FALLING) event.
Something similar to this example:
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
}
void loop() {
digitalWrite(ledPin, state);
}
void blink() {
state = !state;
}
Mind that you may still need some debouncing strategy.
Also, you don't need to use an interrupt for that, but then you'd need some edge-detection algorithm. These are quite well explained in the debouncing article above. I personally prefer these, since interrupt pins in the UNO board are precious enough not to be used with humble button pressings... :o)
/*
Debounce
Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's a
minimum delay between toggles to debounce the circuit (i.e. to ignore noise).
The circuit:
- LED attached from pin 13 to ground
- pushbutton attached from pin 2 to +5V
- 10 kilohm resistor attached from pin 2 to ground
- Note: On most Arduino boards, there is already an LED on the board connected
to pin 13, so you don't need any extra components for this example.
created 21 Nov 2006
by David A. Mellis
modified 30 Aug 2011
by Limor Fried
modified 28 Dec 2012
by Mike Walters
modified 30 Aug 2016
by Arturo Guadalupi
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Debounce
*/
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// Variables will change:
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
// set initial LED state
digitalWrite(ledPin, ledState);
}
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}

How do I configure an interrupt for the hardware PWM on the Arduino Due?

I'm working on a project on the Arduino Due to make a digital synthesizer. I will use PWM to generate an output wave at the desired notefrequency, and sample the wave at 192kHz.
I am able to get PWM out at the desired frequency and adjust the pulse width (tested with oscilloscope), but I need to configure the interrupt so that I can calculate the next needed PWM value for different types of waves at different audible frequencies (sin, sawtooth, etc.). Each time the interrupt triggers (at 192kHz), a function will calculate the next pulse width value based on the note value (audible frequency).
Here is my code so far. I am able to get the PWM to work, but my dummy code in the interrupt (which turns a pin on and off) does not toggle the pin. I have tested this with an oscilloscope. I know that the problem with the code is the interrupt not triggering/executing properly, because the output pin is set high in the setup code, and that also happens on the oscilloscope. However, the interrupt test pin does not toggle. What am I missing?
uint32_t pwmPin = 8; // PWM output pin
uint32_t channel = g_APinDescription[pwmPin].ulPWMChannel;
uint32_t sampFreq = 192000ul; // sample at 192kHz
uint32_t clkAFreq = 42000000ul;
uint32_t pwmFreq = (clkAFreq * 2)/sampFreq;
uint16_t dutyPercent = 50;
uint16_t dutyAct = pwmFreq * (100-dutyPercent) / 100;
void setup() {
// put your setup code here, to run once:
pinMode(5, OUTPUT); // interrupt test pin
pmc_enable_periph_clk(PWM_INTERFACE_ID);
PWMC_ConfigureClocks(clkAFreq, 0, VARIANT_MCK);
PIO_Configure(
g_APinDescription[pwmPin].pPort,
g_APinDescription[pwmPin].ulPinType,
g_APinDescription[pwmPin].ulPin,
g_APinDescription[pwmPin].ulPinConfiguration);
//uint32_t
channel = g_APinDescription[pwmPin].ulPWMChannel;
PWMC_ConfigureChannel(PWM_INTERFACE, channel, clkAFreq, 0, 0);
PWMC_SetPeriod(PWM_INTERFACE, channel, pwmFreq);
PWMC_EnableChannel(PWM_INTERFACE, channel);
PWMC_SetDutyCycle(PWM_INTERFACE, channel, dutyAct);
PWMC_EnableChannelIt(PWM_INTERFACE, channel);
dutyPercent = 50; //square wave
}
void loop() {
// put your main code here, to run repeatedly:
}
void PWM_Handler() // this is what I looked up in startup_sam4s.c
{
int i; //
digitalWrite(5, HIGH); // toggle pin
i++; // delay a little
digitalWrite(5, LOW); // toggle pin
}
For anyone who stumbles across this, here is how I got the interrupt to work:
uint32_t totalTime = 0; // total elapsed time
uint32_t pwmPin = 8; // PWM output pin
uint32_t irqPin = 5; // interrupt test pin
uint32_t channel = g_APinDescription[pwmPin].ulPWMChannel; // set channel for PWM out
uint32_t sampFreq = 192000ul; // sampling frequency (Hz)
uint16_t maxDutyCount = 255;
uint32_t clkAFreq = 42000000ul; // clock frequency (Hz)
uint32_t pwmFreq = (clkAFreq * 2)/sampFreq; // calculate PWM frequency
uint16_t dutyPercent = 128; // starting duty percent
uint16_t dutyAct = pwmFreq * (maxDutyCount-dutyPercent) / maxDutyCount; //
void setup() {
// put your setup code here, to run once:
pinMode(irqPin, OUTPUT);
pmc_enable_periph_clk(PWM_INTERFACE_ID);
PWMC_ConfigureClocks(clkAFreq, 0, VARIANT_MCK);
PIO_Configure(
g_APinDescription[pwmPin].pPort,
g_APinDescription[pwmPin].ulPinType,
g_APinDescription[pwmPin].ulPin,
g_APinDescription[pwmPin].ulPinConfiguration);
channel = g_APinDescription[pwmPin].ulPWMChannel; // channel 5
PWMC_ConfigureChannel(PWM_INTERFACE, channel, clkAFreq, 0, 0);
PWMC_SetPeriod(PWM_INTERFACE, channel, pwmFreq);
PWMC_EnableChannel(PWM_INTERFACE, channel);
PWMC_SetDutyCycle(PWM_INTERFACE, channel, dutyAct);
PWM_INTERFACE->PWM_IER1 = 0x20; //enable interrupt on channel 5
PWM_INTERFACE->PWM_IDR1 = 0xFFFFFFDF; //enable interrupt on channel 5
PWM_INTERFACE->PWM_IER2 = 0x00002001; //enable interrupt on channel 5
PWM_INTERFACE->PWM_IDR2 = 0xFFFFDFFE; //enable interrupt on channel 5
NVIC_DisableIRQ(PWM_IRQn); // set up interrupt
NVIC_ClearPendingIRQ(PWM_IRQn);
NVIC_SetPriority(PWM_IRQn, 0);
NVIC_EnableIRQ((IRQn_Type)36); //NVIC_EnableIRQ(PWM_IRQn);
PWMC_EnableChannel(PWM_INTERFACE, channel);
//Enable of the Interrupts (writing CHIDx and FCHIDx
//in PWM_IER1 register, and writing WRDYE, ENDTXE,
//TXBUFE, UNRE, CMPMx and CMPUx in PWM_IER2 register)
}
void loop() {
}
void PWM_Handler(void) // PWM interrupt handler
{
volatile long dummy = PWM_INTERFACE->PWM_ISR1; // clear interrupt flag
dummy = PWM_INTERFACE->PWM_ISR2; // clear interrupt flag
//your code here!
}

program not working on arduino leonardo

I have a program that works on an uno with serial output but does not work on a leonardo with the only changes being the keyboard press and release. I am using a coin mech and it is outputting a pulse when a coin is added. It did however trigger a load of times when the cable came loose from the pin the signal was being sent from
const int coinInt = 0;
//Attach coinInt to Interrupt Pin 0 (Digital Pin 2). Pin 3 = Interrpt Pin 1.
volatile float coinsValue = 0.00;
//Set the coinsValue to a Volatile float
//Volatile as this variable changes any time the Interrupt is triggered
int coinsChange = 0;
//A Coin has been inserted flag
void setup()
{
attachInterrupt(coinInt, coinInserted, RISING);
//If coinInt goes HIGH (a Pulse), call the coinInserted function
//An attachInterrupt will always trigger, even if your using delays
}
void coinInserted()
//The function that is called every time it recieves a pulse
{
coinsValue = coinsValue + 0.05;
//As we set the Pulse to represent 5p or 5c we add this to the coinsValue
coinsChange = 1;
//Flag that there has been a coin inserted
}
void loop()
{
if(coinsChange == 1)
//Check if a coin has been Inserted
{
coinsChange = 0;
//unflag that a coin has been inserted
Keyboard.press('+');
delay(100);
Keyboard.releaseAll();
//Print the Value of coins inserted
}
}
It may not be the problem, but I see that coinsChanged is set in the interrupt function and tested in loop(), but is not declared volatile.
I'd change
int coinsChange = 0;
to
volatile int coinsChange = 0;

Arduino countdown within delay loop

What a great learning experience my first Arduino project is turning out to be.. I would now like to add a countdown until a sensor reading is taken and displayed, which will repeat infinitely. I've got the sensor and LCD display working fine but my loop is not quite right.. Should I be using a while() of some sort? How do I keep the timer ticking during the big delay between readings?
/*Code for self-watering plant with LCD readout*/
// value for LCD params
char ESC = 0xFE;
// analog input pin that the soil moisture sensor is attached to
const int analogInPin = A1;
// value read from the soil moisture sensor
int sensorValue = 0;
// if the readings from the soil sensor drop below this number, then turn on the pump
int dryValue;
// countdown timer until next soil reading
int timerValue = 9;
void setup() {
pinMode(12, OUTPUT);
// initialize serial communications at 9600 bps:
Serial.begin(9600);
// Set the "dry" value of soil on turning on the device
dryValue = analogRead(analogInPin);
// pause before intialize LCD
delay(2000);
// Initialize LCD module
Serial.write(ESC);
Serial.write(0x41);
Serial.write(ESC);
Serial.write(0x51);
// Set Contrast
Serial.write(ESC);
Serial.write(0x52);
Serial.write(40);
// Set Backlight
Serial.write(ESC);
Serial.write(0x53);
Serial.write(5);
//print the dry value to serial
Serial.print("Dry = " );
Serial.print(dryValue);
Serial.print(" ");
}
void loop(){
watering();
// wait some time (really should be delay(86400000))
delay(10000);
}
void printTimer(){
// Set cursor line 1, column 16
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x0F);
// print the timer value
Serial.print(timerValue);
timerValue = timerValue - 1;
if(timerValue == 0){
timerValue = 9;
}
}
void printVal(){
// set cursor line 2, column 1
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x40);
// print the sensor to the serial monitor:
Serial.print("Sensor = " );
Serial.print(sensorValue);
Serial.print(" ");
printTimer();
}
void watering(){
// read the analog in value:
sensorValue = analogRead(analogInPin);
//turn on the water pump for some time if the soil is too dry
if(sensorValue < dryValue){
digitalWrite(12, HIGH);
delay(2000);
digitalWrite(12, LOW);
}
else {
printVal();
}
}
It's actually really simple: Don't delay. Instead, initialize a timer to run a routine whenever it overflows or hits a certain value. Examine the datasheet for the microcontroller used in your Arduino for the specific bits to frob (note that the Arduino libraries use the timer 0 overflow vector for themselves), and the avr-libc documentation for how to denote the ISR(s) for the timer. Your loop() then becomes a big sleep while the timer runs the entire show for you.
I would use a timer library for Arduino like this http://playground.arduino.cc//Code/SimpleTimer
Just download the library, put it in the "libraries" folder in your sketchbook and restart your Arduino IDE to load the new library.
Then your code would look something like this. Basically what it does it updates the screen every loop and then once every 86400000 ms it checks the "watering" function. Just so you know this code would only check the soil once every 24 hours (86400000ms). I think a better solution would be to constantly check the soil and water anytime it is needed. But Im no gardener so maybe there is a reason for just checking once a day.
#include <SimpleTimer.h>
// the timer object
SimpleTimer timer;
void setup() {
Serial.begin(9600);
timer.setInterval(86400000, watering); // how often you would call your watering function is set with the first variable
}
void loop() {
timer.run();
printTimer();
}
void printTimer(){
// Set cursor line 1, column 16
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x0F);
// print the timer value
Serial.print(timerValue);
timerValue = timerValue - 1;
if(timerValue == 0){
timerValue = 9;
}
}
void printVal(){
// set cursor line 2, column 1
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x40);
// print the sensor to the serial monitor:
Serial.print("Sensor = " );
Serial.print(sensorValue);
Serial.print(" ");
printTimer();
}
void watering(){
// read the analog in value:
sensorValue = analogRead(analogInPin);
// send it to the display
printVal();
//turn on the water pump for some time if the soil is too dry
if(sensorValue < dryValue){
digitalWrite(12, HIGH);
delay(2000);
digitalWrite(12, LOW);
}
}

Resources