Hello Everyone,
I'm currently using an Arduino UNO for a Crank/Cam simulator, it's for a hardware in the loop project at work.
New to Arduino and the syntax ( I know Matlab), I'm looking for help with adding a function to the current code that I'm using( Open Source code below, I didn't write it) .
Current code is on a repeating loop and the uses a pre-determined Rpm, the only way I can change it while running the code is opening the "Serial monitor window" and commanding a new Rpm by typing in the exact character(function) + new rpm value(very slow). This is all good for set point testing but I'm looking to automate my test so I can sweep RPM based on a DOE. Some parts of the DOE are randomize and will run >100 hours.
So what I'm wanting to is bring a 0-10[v] (I can settle for 0-5[v]) input into the Arduino UNO board, this signal will come from my Data acquisition equipment. I want the code to read the voltage input as a RPM, 0[v] being 0 [Rpm] and 10[v]: 5000 [RPM]. I’d like the code to adjust the RPM and crank signal based on the voltage input.
I’m looking for TIP, code and any advice to make this possible.
The Arduino out voltage signal is 0-5[v]: 1 output is for our 58X crank signal and the other is for a 4x Cam signal.
/* vim: set syntax=c expandtab sw=2 softtabstop=2 autoindent smartindent smarttab : /
/
- Arbritrary wheel pattern generator
- copyright 2014 David J. Andruczyk
- Ardu-Stim software is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- ArduStim software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with any ArduStim software. If not, see Licenses - GNU Project - Free Software Foundation
*/
#include "defines.h"
#include "enums.h"
#include "serialmenu.h"
#include "sweep.h"
#include "wheel_defs.h"
#include "user_defaults.h"
#include <avr/pgmspace.h>
#include <SerialUI.h>
/* Sensistive stuff used in ISR's /
volatile uint8_t fraction = 0;
volatile uint8_t selected_wheel = DEFAULT_WHEEL;
volatile uint16_t adc0; / POT RPM /
volatile uint16_t adc1; / Pot Wheel select /
volatile uint32_t oc_remainder = 0;
/ Setting rpm to any value over 0 will enabled sweeping by default /
/ Stuff for handling prescaler changes (small tooth wheels are low RPM) /
volatile uint8_t analog_port = 0;
volatile bool adc0_read_complete = false;
volatile bool adc1_read_complete = false;
volatile bool reset_prescaler = false;
volatile bool normal = true;
volatile bool sweep_reset_prescaler = true; / Force sweep to reset prescaler value /
volatile bool sweep_lock = false;
volatile uint8_t output_invert_mask = 0x00; / Don't invert anything /
volatile uint8_t sweep_direction = ASCENDING;
volatile byte total_sweep_stages = 0;
volatile int8_t sweep_stage = 0;
volatile uint8_t prescaler_bits = 0;
volatile uint8_t last_prescaler_bits = 0;
volatile uint8_t mode = FIXED_RPM;
volatile uint16_t new_OCR1A = 5000; / sane default */
volatile uint16_t edge_counter = 0;
/* Less sensitive globals */
uint8_t bitshift = 0;
uint16_t sweep_low_rpm = 0;
uint16_t sweep_high_rpm = 0;
uint16_t sweep_rate = 0;
SUI::SerialUI mySUI = SUI::SerialUI(greeting);
sweep_step SweepSteps; / Global pointer for the sweep steps */
/* Initialization */
void setup() {
extern unsigned long wanted_rpm;
serial_setup();
cli(); // stop interrupts
/* Configuring TIMER1 (pattern generator) */
// Set timer1 to generate pulses
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
// Set compare register to sane default
OCR1A = 1000; /* 8000 RPM (60-2) */
// Turn on CTC mode
TCCR1B |= (1 << WGM12); // Normal mode (not PWM)
// Set prescaler to 1
TCCR1B |= (1 << CS10); /* Prescaler of 1 */
// Enable output compare interrupt for timer channel 1 (16 bit)
TIMSK1 |= (1 << OCIE1A);
// Set timer2 to run sweeper routine
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = 0;
// Set compare register to sane default
OCR2A = 249; /* With prescale of x64 gives 1ms tick */
// Turn on CTC mode
TCCR2A |= (1 << WGM21); // Normal mode (not PWM)
// Set prescaler to x64
TCCR2B |= (1 << CS22); /* Prescaler of 64 */
// Enable output compare interrupt for timer channel 2
TIMSK2 |= (1 << OCIE2A);
/* Configure ADC as per Interrupt-Driven Analog Conversion With an ATMega328p - Glenn Sweeney */
// clear ADLAR in ADMUX (0x7C) to right-adjust the result
// ADCL will contain lower 8 bits, ADCH upper 2 (in last two bits)
ADMUX &= B11011111;
// Set REFS1..0 in ADMUX (0x7C) to change reference voltage to the
// proper source (01)
ADMUX |= B01000000;
// Clear MUX3..0 in ADMUX (0x7C) in preparation for setting the analog
// input
ADMUX &= B11110000;
// Set MUX3..0 in ADMUX (0x7C) to read from AD8 (Internal temp)
// Do not set above 15! You will overrun other parts of ADMUX. A full
// list of possible inputs is available in Table 24-4 of the ATMega328
// datasheet
// ADMUX |= 8;
// ADMUX |= B00001000; // Binary equivalent
// Set ADEN in ADCSRA (0x7A) to enable the ADC.
// Note, this instruction takes 12 ADC clocks to execute
ADCSRA |= B10000000;
// Set ADATE in ADCSRA (0x7A) to enable auto-triggering.
ADCSRA |= B00100000;
// Clear ADTS2..0 in ADCSRB (0x7B) to set trigger mode to free running.
// This means that as soon as an ADC has finished, the next will be
// immediately started.
ADCSRB &= B11111000;
// Set the Prescaler to 128 (16000KHz/128 = 125KHz)
// Above 200KHz 10-bit results are not reliable.
ADCSRA |= B00000111;
// Set ADIE in ADCSRA (0x7A) to enable the ADC interrupt.
// Without this, the internal interrupt will not trigger.
ADCSRA |= B00001000;
// pinMode(7, OUTPUT); /* Debug pin for Saleae to track sweep ISR execution speed /
pinMode(8, OUTPUT); / Primary (crank usually) output /
pinMode(9, OUTPUT); / Secondary (cam usually) output /
pinMode(10, OUTPUT); / Knock signal for seank, ony on LS1 pattern, NOT IMPL YET */
sei(); // Enable interrupts
// Set ADSC in ADCSRA (0x7A) to start the ADC conversion
ADCSRA |= B01000000;
/* Make sure we are using the DEFAULT RPM on startup */
reset_new_OCR1A(wanted_rpm);
} // End setup