Show Posts
Pages: 1 [2] 3 4 ... 22
16  Using Arduino / General Electronics / Re: Multi-phase buck converter on: March 07, 2014, 04:22:00 pm
I'd be leery of this code.  It doesn't do anything intentional to establish any particular phase relationship between Timer1 and Timer2; it just gets lucky.  Here's why it seems to work:
  • The last thing that the internal startup code does is to set up and start Timer2.  Timer2 runs at 1/64 of the system clock, so it's still at zero when setup() executes.
  • Timer1 is set to full scale for its mode - 8-bit phase-correct PWM, mode 1 - rather than half-scale, as claimed in the text accompanying this code.  The code sets it explicitly to 0x7FFF, but Timer1 ignores the most significant byte in mode 1, and sets itself to 0xFF.  That more or less works, because the phase-correct mode counts up to the top, and then down to the bottom, rather than rolling over.  Timer1 is set to one tick away from zero, upcounting, at a time when Timer2 is at zero, upcounting.  On the next tick, Timer2 starts counting down, while Timer1 counts up.  They're almost 180 degrees out pf phase, but that's largely a matter of luck.  If the next version of the IDE adds code between setting Timer2 and calling setup(), or if you add code at the beginning of setup(), the phase relationship will be less accurate.  With just a couple of analogRead()'s, it gets off pretty far.

Here's an 8-phase PWM controller, made for applications like this: http://www.irf.com/product-info/datasheets/data/pb-chl8318.pdf.  It costs about $3 US in big quantities.  I didn't readily find any for sale in singles.  Maybe the manufacturer will sample a couple to you.

I believe that an Uno won't lend itself well to generating the PWM pulses you want.  A Due might.  The datasheet claims, "Up to 8-channel 16-bit PWM," - exactly the right number - but I don't know how that's implemented in the Due, or supported in the IDE.  If you want to investigate that, you might try the Due forum, here:  http://forum.arduino.cc/index.php?board=87.0.

I'll echo Grumpy Mike's sentiment, and vote that you prototype something with less current.  A buck converter runs just one step ahead of the grim reaper - if a driver doesn't switch off, the supply voltage shows up on the output in short order.  This statement:
Quote
I am new to microcontrollers ...
suggests that you'll have multiple rounds of debugging, and, with this project, that suggests that you might see a little smoke.
17  Using Arduino / Programming Questions / Re: Interruptions using TimerOne.h library on: March 04, 2014, 11:22:33 pm
If you're new to this, you may want to try something simpler.  Then, when that works, try adding some additional functions.  Based on what you've said here, it looks like you're trying to write the whole program at once.  When you do that, it can be very difficult to figure out what isn't working.

It sounds like you're making a traffic light controller.  I'll suggest that you try making it work like a simple automatic traffic light:  turns red for a while, and then turns green for a while - you don't mention a yellow light, so I presume that you're not implementing one.  If you can't make it work, you can post your code, describe what you expected, and describe what you it does instead.  If you can make it work, then you can try to add another function, and, when you run into trouble, post code, a clear description of what you expect, and a clear description of what it does.  When you post code, please make sure that you post something that compiles, so that others can load it straight into an Arduino and see how it works.

So far, you haven't told us much.  Your description is hard to understand, and you don't show any code.  It's difficult for anyone to offer any help.

As you get further into this project, you may find that it works well as a state machine.  Here are a couple of references that discuss state machines:
18  Using Arduino / Programming Questions / Re: External interrupt while going to sleep with ADXL345 ends in "endless wait" on: March 04, 2014, 07:12:54 pm
Somebody else had a similar problem, and fixed it, here: http://forum.arduino.cc/index.php?topic=218224.  Maybe that solution will work for you, too.
19  Using Arduino / Audio / Re: Comparing frequencies with FFT on: March 01, 2014, 10:45:48 am
OK, it sounds like the audio part of this problem is to discern the difference between these two conditions:
  • A quiet room, and
  • An otherwise quiet room with a baby crying in it.
The fact that it's very easy for a human to make that distinction is promising.  Here are some differences that we'd expect to find between when the baby cries:
  • The total audio signal will be louder overall - maybe a lot louder
  • The signal will have significant content at baby-crying frequencies
A start might be to find some audio files of babies crying, play them to your Arduino in a quiet room, and observe the output of the FFT with and without crying.  It will be easier to see the differences graphically.  I usually print the output to the serial monitor, copy it to a spreadsheet, and graph it.  There may be better or more convenient ways to do it.  A quick google finds a number of mp3's of babies crying.

A more fundamental approach would be to use test tones with known spectral content, to verify that the assembled project accurately reflects the audio signal.  I'd recommend this if it's important that you're able to accurately characterize how your system works, or how you derived your solution.  mp3 files of test tones are easy to google.

I have no expertise on the spectral content of babies crying.  I think that this:
Quote
A baby's cry has a frequency of 3500kHz on average.
is probably a typographical error, and that you meant to say 3500 Hz, or maybe 350 Hz.  3500 Hz is the third-highest white key on a concert piano - it's a really high note.  The first estimate of the pitch of a baby's cry that I found was 515 Hz.

Note that the output that you can expect from your code is a logarithmic representation of the Fourier transform.  That representation compresses the magnitude of the spectrum: it de-emphasizes large spectral components, and emphasizes small ones.  You might want to experiment with a linear representation.  You can find information about how to get that in the fft_read_me.txt file in the openmusiclabs FFT library.

What's your current understanding of the meaning of the FFT output?
20  Using Arduino / Audio / Re: Comparing frequencies with FFT on: March 01, 2014, 12:10:08 am
I need to detect a baby's cry out of the surrounding sounds.
For what purpose?  Do you envision a do-it-yourself device minding the baby while you barbecue steaks in the back yard, or nap in the solarium?  I can't really think of another reason for this function.  I'm not sure that I want to be part of it -  I'd rather not have to answer in the next life for the sufferings of an infant in this one.

Maybe you just want to do this for the sheer intellectual joy of proving that it can be done.  Maybe you're talking about some non-human baby crying.  I'm OK with that.  If that's so, then you'll want to explore the whole idea of the Fourier transform, and what it means.  Then, look at the digital Fourier transform, and finally at its special case, the fast Fourier transform.  I'd start with the Wikipedia, and google from there.  Ultimately, you want to understand what the output of the FFT describes, and how it's related to the physical reality that gives rise to it.

You'll also want to read the datasheet for the processor you plan to use.  You need to tell us which one.  I assume that you're using an Uno.  The section on the Analog-to-Digital Converter (ADC) will be especially helpful, since that's the engine that will acquire your data.  The openmusiclabs code that you've incorporated runs the ADC at nearly 40 kHz - faster than the datasheet recommends, and maybe faster than you want, but not so fast that the data isn't usable.  Or, so I read and hear.

You'll need to characterize the sound you want to identify.  I don't really know how you're going to get sample data from a baby crying.  Maybe just run a recorder until you get what you want, or maybe introduce a recorder during the inevitable moments when somebody else unsuccessfully tries to quiet the baby.  For heaven's sake, don't make it cry just to get audio samples.

You'll also need to characterize the ambient sound in the environment where you'll use it.  Obviously, if you're trying to pick out your baby's cry in a nursery full of other children, it'll be a lot harder than picking it out against the background noise of, say, the air conditioner fan blowing in the background.

When you can describe the FFT's of those two sounds - baby crying and not baby crying - then you'll have to devise a way of telling the difference in the sketch.  That might be easy, or it might be hard.

It sounds like you're relatively new to audio analysis, to programming, and to this hardware.  You've selected a very challenging early project.  If you have a high tolerance for frustration and disappointment, then by all means, proceed.  If not, you might be better advised to start with easier projects with hope of quicker success, and less rigorous theoretical demands.

21  Using Arduino / Audio / Re: Comparing frequencies with FFT on: February 28, 2014, 03:38:45 pm
What should I do?
Please be more specific.
  • What are you trying to accomplish?
  • You showed some code - did it work the way you expected?
  • Presuming it didn't work like you hoped- since you're posting here - what did it do?

And, you can do something about the Timer0 interrupt.  Your code disables it early on, and then calls delay(), which relies on the Timer0 interrupt in order to function.  Either refrain from disabling the interrupt, or don't call delay().
22  Using Arduino / Audio / Re: Frequency modulation with arduino uno on: February 21, 2014, 02:00:52 pm
I like seeing abbreviated code.  It keeps me from having to pore through hundreds of irrelevant lines.  When you abbreviate code, though, I'll suggest that you test it before posting, and determine that it compiles, runs, and demonstrates the problem that you're trying to resolve.  If it doesn't compile or run, or it's overly complex, a lot of potential thread participants will skip it and move on to the next thing.  And, obviously, if it doesn't demonstrate the problem, posting the code won't help solve it.  Here's a snippet from "How to use this forum," found here - http://forum.arduino.cc/index.php/topic,148850.0.html - Item #11, "Tips for getting the most out of your post:"
Quote
Post a complete sketch (program code)! If you don't you waste time while people ask you to do that. However, with coding problems, if possible post a "minimal" sketch that demonstrates the problem - not hundreds of lines of code. If the problem goes away in the minimal sketch, it wasn't where you thought it was.

From what I see, running the timer at 2 kHz won't resolve the issue - it'll just make it appear less frequently.  The problem is that the TIMER0_COMPA ISR takes longer to execute than the time between TIMER1_OVF interrupts.  Depending on where in the TIMER1 cycle the TIMER0 interrupt occurs, it will execute through two TIMER1 interrupts, and you'll miss one.  The appearance, from an audio viewpoint, will be that the TIMER1 interrupt slows down; in fact, it will just be missing some updates, thus stretching out the output waveform in time. 

Another alternative might be to disable the Timer0 interrupt, poll the timer status in the in the Timer1 interrupt, and execute the Timer0 ISR code when Timer0 has fired.  The Timer0 code takes only a little longer than a Timer1 interrupt.  The fast PWM mode updates the OCR at rollover no matter when the OCR is changed, so, in theory, you have nearly twice the Timer1 duration to manage that calculation if you start early.  That might work, if the rest of the sketch can tolerate having the Timer1 ISR take control for more than its cycle time. 

Note that these notions are strictly intuitive - I haven't tested any of these theories, or tried any proposed solutions.
23  Using Arduino / Audio / Re: Frequency modulation with arduino uno on: February 19, 2014, 09:48:52 pm
The posted code doesn't compile for me.  It seems to be missing a '}' in the function generateSquarewaveosc().  That makes me suspect that this isn't the code you were actually testing, so I'm not willing to spend too much time on it.

This
Code:
ISR(TIMER0_COMPA_vect){
  //routine that fires at a rate of 4000hz
  osc1count = fixedmathmultiply(osc1phasedelta,pgm_read_word(&(freqModValArray[LFOval/2])));
}
definitely takes too long.  Testing its timing with this code
Code:
#include <avr/interrupt.h>   //add interrupts
#include <avr/io.h>          //no idea
#include <avr/pgmspace.h>    //to store values in progmem
#include "Arduino.h"

//Array filled with values used for modulating the oscillator number with as conversion base 1024, so fixed point math can be used. contains 256 unsigned ints
prog_uint16_t freqModValArray[] PROGMEM = {
  1024, 1027, 1030, 1032, 1035, 1038, 1041, 1044, 1047, 1049, 1052, 1055, 1058, 1061, 1064, 1067, 1070, 1072, 1075, 1078, 1081, 1084, 1087, 1090, 1093, 1096, 1099, 1102, 1105, 1108, 1111, 1114, 1117, 1120, 1123, 1126, 1129, 1132, 1135, 1139, 1142, 1145, 1148, 1151, 1154, 1157, 1160, 1164, 1167, 1170, 1173, 1176, 1179, 1183, 1186, 1189, 1192, 1196, 1199, 1202, 1205, 1209, 1212, 1215, 1219, 1222, 1225, 1229, 1232, 1235, 1239, 1242, 1245, 1249, 1252, 1256, 1259, 1262, 1266, 1269, 1273, 1276, 1280, 1283, 1287, 1290, 1294, 1297, 1301, 1304, 1308, 1311, 1315, 1319, 1322, 1326, 1329, 1333, 1337, 1340, 1344, 1348, 1351, 1355, 1359, 1362, 1366, 1370, 1373, 1377, 1381, 1385, 1388, 1392, 1396, 1400, 1404, 1407, 1411, 1415, 1419, 1423, 1427, 1431, 1434, 1438, 1442, 1446, 1450, 1454, 1458, 1462, 1466, 1470, 1474, 1478, 1482, 1486, 1490, 1494, 1498, 1502, 1506, 1510, 1515, 1519, 1523, 1527, 1531, 1535, 1539, 1544, 1548, 1552, 1556, 1561, 1565, 1569, 1573, 1578, 1582, 1586, 1591, 1595, 1599, 1604, 1608, 1612, 1617, 1621, 1625, 1630, 1634, 1639, 1643, 1648, 1652, 1657, 1661, 1666, 1670, 1675, 1679, 1684, 1689, 1693, 1698, 1702, 1707, 1712, 1716, 1721, 1726, 1730, 1735, 1740, 1745, 1749, 1754, 1759, 1764, 1768, 1773, 1778, 1783, 1788, 1793, 1797, 1802, 1807, 1812, 1817, 1822, 1827, 1832, 1837, 1842, 1847, 1852, 1857, 1862, 1867, 1872, 1877, 1882, 1888, 1893, 1898, 1903, 1908, 1913, 1919, 1924, 1929, 1934, 1940, 1945, 1950, 1956, 1961, 1966, 1972, 1977, 1982, 1988, 1993, 1999, 2004, 2009, 2015, 2020, 2026, 2031, 2037, 2042, 2048
};

volatile int LFOval;
volatile unsigned long osc1count;
volatile unsigned long osc1phasedelta;

void setup() {
  Serial.begin(115200);
  Serial.println("OK");
}

void loop() {
  const uint16_t iter = 31250;
  uint32_t st, fin, dur;
  st = micros();
  for (uint16_t i = 0; i < iter; i++) {
    osc1count = fixedmathmultiply(osc1phasedelta, pgm_read_word(&(freqModValArray[LFOval / 2])));
    LFOval++;
    LFOval &= 0xFF;
    osc1phasedelta += 0x123456U;
  }
  fin = micros();
  dur = fin - st;
  Serial.print(iter);
  Serial.print(" ");
  Serial.print(dur);
  Serial.print(" ");
  Serial.print((float)iter * 1000000.0 / (float)dur);
  Serial.println();
}

unsigned long fixedmathmultiply(unsigned long number, int multiplier) {
  unsigned long numberlsb = number & 65535ul; //get the lsb 16-bits of the number variable
  unsigned long numbermsb = number >> 16 ;   // get the msb 16-bits of the number variable
  numberlsb = numberlsb * multiplier;
  numbermsb = numbermsb * multiplier;
  numberlsb = numberlsb >> 10;
  numbermsb = numbermsb << (6);
  unsigned long result = numbermsb + numberlsb;
  return result;
}
yields this output:
Code:
OK
31250 1081680 28890.25
31250 1081720 28889.18
31250 1081716 28889.28
which is mostly your code, it takes about 1/29K =~ 34.4 us to run. There's only 32.0 us between Timer1 interrupts.  This code takes longer to run than the interval between Timer1 interrupts.  You'll miss a Timer1 interrupt from time to time, and your PWM frequency will appear to slow down.  It won't really slow down - it'll just keep the same value every now and then, and appear to slow down.  There's loop overhead in the test code, sure - but there's interrupt overhead in the ISR, too, what with all the pushing and popping.  I'm guessing that they're roughly the same, or, if they're not, that the test code runs a bit faster than the ISR.  That's an intuitive guess.

One way to alleviate this would be to only set a flag and maybe bump a counter in the Timer0 interrupt, and let loop() manage the calculations.  The Timer0 ISR won't overrun the time between Timer1 interrupts, and loop should have enough time, at 4 kHz, to keep up.

You may hope to keep loop() busy with other activities, so it won't be able to keep in step with the update task.  If that's so, you could try reenabling interrupts inside the Timer0 interrupt.  That way, though, is fraught with peril: it's hard enough to troubleshoot interrupts when they happen one at a time.  When they start interrupting each other, it can be really hard to tell what's going on.  This might work if you don't anticipate using other interrupts in your project.

You might want to consider using Timer2 instead of Timer0.  If you leave Timer0 alone, you'll have access to the Arduino timing functions.  Alternatively, if you keep a running count of Timer0 interrupts, you'll have a way to determine how long things take.
24  Using Arduino / Programming Questions / Re: Pin and timer interrupt in same program on: February 19, 2014, 05:06:27 pm
... please send your code.
Here's the revised function myWatchdogEnable().  Miniimal changes to this function, no other changes to the code:
Code:
void myWatchdogEnable (const byte interval)
{

  byte adcsra_save = ADCSRA;
  byte prr_save = PRR;

  ADCSRA = 0;  // disable ADC
  PRR = 0xFF; // turn off various modules
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
  noInterrupts();
  attachInterrupt (0, wake, FALLING);   // allow grounding pin 2 to wake us
  // turn off brown-out enable in software
  MCUSR = 0;                          // reset various flags
  WDTCSR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCSR =  0b01000000 | interval;    // set WDIE, and appropriate delay
  wdt_reset();
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS);
  sleep_enable();
  interrupts();  //  [Edit: Added this.]
  sleep_cpu();
  sleep_disable();
  detachInterrupt (0);      // stop LOW interrupt
  //sleep_disable();
  ADCSRA = adcsra_save; // stop power reduction
  PRR = prr_save;
}  // end of myWatchdogEnable
I don't claim that this is optimized, or that everything it does is necessary or even makes sense - just that it didn't exhibit the problem you described.  I'll bet it could still benefit from more work.

Code:
Might be that you have had less bouncing on your switch.
I doubt it.  I used a paper clip.  I tested it with an interrupt counter, and it incremented by as much as 100 for a single operation.
25  Using Arduino / Programming Questions / Re: How to use port manipulation interrupts? on: February 18, 2014, 04:19:32 pm
That code doesn't compile.  The IDE objects to a duplicate ISR definition.

You can't use the same ISR twice.  You can have only one PCINT0 ISR.  It responds to a change on either pin.  It's the sketch's job to identify the changes.

How can i differentiate between the 2 pins and call their respective ISR?
Answer:
With pin change interrupts, you'll have to keep track of the last state of the active pins, and compare it with their new state in order to determine which pin(s) changed.
  • Read the pins
  • Store their current state
  • When the interrupt happens, compare the previous value to the new value.
  • Determine which pins changed, and how they changed
  • Do something with that information
  • Update the current state of the pins
26  Using Arduino / Programming Questions / Re: How to use port manipulation interrupts? on: February 18, 2014, 03:12:18 pm
This line
Code:
  PCICR = _BV(PCIE0); //Enable interrupts from PCINT0 to PCINT7
enables the pin change 0 interrupt.  In order for a pin change interrupt to occur, the appropriate bit(s) in  register PCMSK0 have to be set as well.

You want to enable a pin change interrupt on pin 10.  From the pin mapping shown here - http://arduino.cc/en/Hacking/PinMapping2560#.UwO36vmQwnM - pin 10 corresponds to PCINT4.  First, we check which group PCINT4 falls into, and that's the first group, controlled by PCMSK0.  Looking at the register description for PCMSK0, the mask for PCINT4 is bit 4.  So, to enable only the interrupt on Pin 10:
Code:
PCICR = _BV(PCIE0);
PCMSK0 = _BV(PCINT4);
Other pins might fall into other groups.  For example, PCINT10, digital pin 14, falls into the second group, controlled by PCIE1 in PCICR; and PCINT19, on analog pin 11, falls into the third group, controlled by PCIE2.

This ISR will be associated with all eight pin change interrupts controlled by PCIE0, and those are PCINT0 through PCINT7.  To get the name of the ISR, we look at the list of interrupt vectors in chapter 14, "Interrupts," of the datasheet.  That shows PCINT0 as the name of Pin Change Interrupt Request 0.  From my experience, the way to derive the interrupt vector is this:  Replace every spaces appearing in the name shown in the interrupt table with an underscore: "_"; then add "_vect" at the end, and that's what goes into the ISR declaration statement.  So, for PCINT0, with no spaces, that becomes PCINT0_vect, and the ISR starts with
Code:
ISR(PCINT0_vect) {
27  Using Arduino / Programming Questions / Re: input capture on: February 18, 2014, 01:12:36 pm
Please:
  • Indent consistently, or use Tools->Auto Format to make your code more readable.
  • Tell us what it does.  The phrase, "my code is not working," lacks descriptive power.
I see a couple of things that will keep this code from doing what you want:

This
Code:
  TCCR1B=prescalebits;
starts Timer1 using the prescaler you've selected.  However, it's followed by this
Code:
  TCCR1B=1<<ICES1;
which sets the input capture edge select bit to 1, and stops the timer.  With the timer stopped, ICR1 will always have the same value.  I don't think that's what you wanted.

This
Code:
if(index=2)
sets index to 2, and then tests it to see if its something other than zero.  The test always passes, so it prints the values and waits a second.  However, with Timer1 stopped, t1 is always the same as t2, and the elapsed time always reports zero.  I don't think that's what you wanted, either.

The input signal will presumably continue toggling while the sketch delays between samples.  The input capture interrupt isn't disabled, so index will likely be something big, and t1 and t2 will already be set, when the system comes out of delay.  Looking for equality with 2 will lead to disappointment.  You may want to examine of managing the capture interrupt between samples, or alternative ways of writing the ISR, to avoid that condition.
28  Using Arduino / Programming Questions / Re: How to stop a timer when the button is pressed again on: February 18, 2014, 11:12:13 am
And, after you look at blink-without-delay, try this:http://www.gammon.com.au/forum/?id=12316
29  Using Arduino / Programming Questions / Re: How to use port manipulation interrupts? on: February 18, 2014, 10:22:37 am
Read the datasheet.  The link can be found on this page:  http://arduino.cc/en/Main/ArduinoBoardMega2560#.UwN71fmQxCI.  Understand the pin change interrupts in chapter 15, "external Interrupts.".  Do some experiments.  Post some code that compiles and does something.  Tell us what it does, and what you expected it to do.
30  Using Arduino / Programming Questions / Re: How to use port manipulation interrupts? on: February 17, 2014, 09:12:14 pm
Code:
PCICR = _BV(PCIE0); //Enable pin change interrupts
PCMSK0 = 1 // - I believe this is required to work out from which pin on a certain port the interrupt came from
ISR(INT1_vect)
{ // starts the ISR
}
Here's how I read that code:  The first line enables pin change interrupts on pins PCINT0:7.  The second line masks all but PCINT0.  By my reading of the schematic and the pin mapping, that will give you a pin change interrupt on digital pin 53 only.  Whenever the processor sees a change on pin 53, it'll throw a PCINT0 interrupt, and vector to the memory location associated with that interrupt.

Here the code will fail, though.  You've created an ISR for INT0, an external interrupt, on pin 21 as I read it.  There's no ISR for PCINT0, so the processor will go to some location defined for bad interrupt vectors, and reset.  I think you want to establish the ISR with this:
Code:
ISR(PCINT0_vect) {

Reading between the lines, it looks like you aren't entirelyup to speed on the difference between INT7:0 and PCINT23:0.  You might want to read the about "External Interrupts" in the datasheet, and satisfy yourself that you know how these interrupts work, and that you know the difference between between them.  You can find a link to the datasheet here:  http://arduino.cc/en/Main/ArduinoBoardMega2560#.UwKt7fmQxCI.  Then, you might want to do some experiments with simple projects to satisfy yourself that you know how to get the results you want, before trying to integrate these interrupts into an already complicated project.

If you're looking for processing speed, and you don't need the pins for something else, you might want to use INT7:0 for this purpose.  You'll have a separate ISR for each pin, so you won't need to determine which pin changed.  You'll also be able to select the edge that triggers the interrupt, so you won't have to resolve that, either.  With pin change interrupts, you'll have to keep track of the last state of the active pins, and compare it with their new state in order to determine which pin(s) changed.
Pages: 1 [2] 3 4 ... 22