Show Posts
Pages: 1 ... 4 5 [6] 7
76  Forum 2005-2010 (read only) / Interfacing / Re: encoder on: April 17, 2008, 04:39:46 am
I'm guessing you've already considered this but retrofitting it to the extant UI code would be too challenging, but I'll suggest it anyway:

Why not implement a sorted list of objects ("solenoid activations") comprising { count value, solenoid number, link to next object }, inserting objects into the list (using an insertion sort) as they are weighed?

At weighing time, calculate the encoder count value that the solenoid needs to be activated by adding the current count value to the known "distance" (in counts) that the appropriate carrier is away from the balance. Each object will therefore know at what count value it needs to be activated (and which solenoid).

Solenoid activation becomes trivial as you simply need to watch the current count value and when it exceeds the count value of the object at the head of the list, activate the solenoid indicated by that object, then remove the object from the list. Since the list is sorted by monotonically increasing encoder value, the next object in the list will correspond to the next solenoid activation.

You need to pre-calculate (at compile time) the maximum number of objects that may be in the list (which is equal to the length of the belt divided by the minimum distance between objects, assuming worst case is where every object weighed needs to go all the way to the last carrier). This scheme also has the advantage that incoming items need not be equally spaced. If you round up the max objects to the nearest power of two, you can use a block of memory and mask arithmetic to implement a ring-buffer. This will save you a byte per object for the next-object pointer, but will complicate the insert operation as you need to ripple-shift the objects further down the list.
77  Forum 2005-2010 (read only) / Interfacing / Re: Button Firing Interrupt Causes Code To Stop on: October 06, 2009, 05:54:42 pm
This logic:

   if (time[0] < 24)
    else if (time[0] == 24)
      time[0] = 0;

is wrong in both setMinutes() and setHours(), as it only increments the hours if its 23 or less. Think about what happens when time[0] is 23 when it enters that code segment.

you want something like:

if (time[0] == 24) time[0] = 0;

instead of the block above in both functions.
78  Forum 2005-2010 (read only) / Interfacing / Re: How do I control fan speed on 12V DC fan? on: January 06, 2009, 05:22:23 pm
330 ohm is fine, it's only going to cause the Arduino to source 15 mA when the output is high (5V). That transistor is a monster, it can take 5 A on the base.
79  Forum 2005-2010 (read only) / Interfacing / Re: How do I control fan speed on 12V DC fan? on: January 05, 2009, 10:16:17 pm
I haven't seen any fans with separate control signals - certainly all PC fans with 3-wire interfaces have pulse-per-rev strobe on yellow ("Count"?). Control is via DC voltage level or PWM (the latter is better for low-speed control). Do a search for "3-wire fan", and look through some of the stuff returned.
80  Forum 2005-2010 (read only) / Interfacing / Re: Large LED project on: September 22, 2008, 11:19:46 pm
Each bank of 50 LEDs is going to pull 1.5A (30mA * 50 in parallel), at that current your 22 ohm resistor is going to drop 33V.

For the Red LED bank you need that resistor to drop 3 V (assume 5V supply and LEDs drop 2V nominal) - so it needs to be 2 ohm. Also at 1.5A that resistor will dissipate 4.5W - I'd go for a 10W wirewound, and it will get HOT.

For the Blue & Green banks the resistor only needs to drop 1.5V (as the LEDs drop 3.5V) so it needs to be 1 ohm. Again it will dissipate 2.25W so a 5W wirewound will suffice.

These calculations will have to be adjusted to account for the Vds of the FET in the on state (which I have assumed above to be 0V). This will further reduce the resistor values.

You might be better to use 1 resistor per LED or even 1 resistor per group of 5 or 10 LEDs, that will increase the value and reduce the power dissipation.
81  Forum 2005-2010 (read only) / Interfacing / Re: Large LED project on: September 21, 2008, 07:42:35 pm
Your initial post mentions PWM, but it doesn't appear that you understand what that means.

PWM (in the context of LED control) is a method of dimming using only on/off switching of a fixed voltage. The switching is undertaken faster than the eye perceives, and the adjustment of the brightness is achieved by varying the ratio of time spent "on" to time spent "off" (aka "duty cycle").

Arduino provides a few PWM outputs which can drive MOSFETS to provide dimming to LEDs.
82  Forum 2005-2010 (read only) / Interfacing / Re: Encoders   mine is a little jumpy on: December 03, 2008, 10:20:55 pm
Try this:
// Rotary Encoder debounce with timer interrupt
#include <FrequencyTimer2.h>

#define encoder0PinA  2
#define encoder0PinB  4

volatile int encoder0Pos = 0;

// Service routine called by a timer interrupt
//extern "C"
void DebounceSwitch()
  static unsigned char rawEncoder0A = 1;
  static unsigned char rawEncoder0B = 1;
  static unsigned char debouncedEncoder0A = 1;  // debounced state of encoder0PinA
  static unsigned char debouncedEncoder0B = 1;  // debounced state of encoder0PinB
  static uint16_t State[] = {
    0xffff, 0xffff     }; // Current debounce status

  rawEncoder0A = digitalRead(encoder0PinA);
  rawEncoder0B = digitalRead(encoder0PinB);

  // Encoder Pin A
  State[0]=(State[0]<<1) | rawEncoder0A | 0xe000;
  if(State[0]==0xf000) { // High --> Low Transition
    if (!debouncedEncoder0B) {   // check channel B to see which way
      // encoder is turning
      encoder0Pos = encoder0Pos + 1;          // CW
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    debouncedEncoder0A = 0;
  if(State[0]==0xefff) { // Low --> High Transition
    debouncedEncoder0A = 1;

  // Encoder Pin B
  State[1]=(State[1]<<1) | rawEncoder0B | 0xe000;
  if(State[1]==0xf000) { // High --> Low Transition
    debouncedEncoder0B = 0;
  if(State[1]==0xefff) { // Low --> High Transition
    debouncedEncoder0B = 1;

  // Clamp (if required)
  if (encoder0Pos < 0) encoder0Pos = 0;
  if (encoder0Pos > 31) encoder0Pos = 31;


void setup() {

  // Encoder setup
  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);       // turn on pullup resistor
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinB, HIGH);       // turn on pullup resistor

  // Timer
  FrequencyTimer2::setPeriod(1000); // 1 ms


void loop() {

  // just use value of encoder0Pos anywhere here

83  Forum 2005-2010 (read only) / Interfacing / Re: Encoders   mine is a little jumpy on: September 16, 2008, 08:23:57 pm
FrequencyTimer2 creates a timer (with setPeriod()), and makes available 2 mechanisms for notification of the timer expiration: a) An external output pin (pin 11), and b) An interrupt.

These two mechanisms are controlled independently, a) is controlled by the enable() and disable() calls, and b) is controlled by the setOnOverflow().

If you don't want to use (a), then just don't ever call enable(). The library will leave pin 11 completely alone for your exclusive use.

If you don't want to use (b), then don't ever call setOnOverflow().

In your case to want to use setOnOverflow() but not enable() and disable().

Pin 3 is available for general purpose I/O but because the PWM output which normally is available at pin 3 uses timer2, you can't use PWM output on pin3 when using this library. Go ahead and use pin 3 for your second encoder input, just check both encoder inputs in the ISR.

edit: better understanding of the library.
84  Forum 2005-2010 (read only) / Interfacing / Re: Encoders   mine is a little jumpy on: September 15, 2008, 08:02:00 pm
1ms is not so frequent for a timer interrupt, only once every 16,000 clock cycles. The interrupt could be made more efficient by using direct access to the pins rather than digitalRead().

Also you might like to read your other sensor inputs, or control your actuators on the same timing schedule (or set a flag to do so in the main loop once the ISR returns). Using counters in the ISR to divide down to a lower frequency before flagging any inputs/outputs for attention in the main loop is also a good way to schedule lower-rate activities.

Edit: Regardless, it is not good practice to use a bouncy switch on an interrupt input.
85  Forum 2005-2010 (read only) / Interfacing / Re: Encoders   mine is a little jumpy on: September 15, 2008, 06:51:34 pm
I contributed something some time ago on this issue, it can be found here.
86  Forum 2005-2010 (read only) / Interfacing / Re: Pitch Detection: Guitar to MIDI on: May 12, 2008, 07:21:40 pm
There is no "non-CPU intensive" algorithm to determine an unknown pitch. FFT is the most efficient known algorithm for this task. Latency will depend on the length of the FFT, which will be determined by how much precision you want - a 128-point FFT at a 44.1 kHz sampling rate will give you ~350 Hz resolution, not enough to discriminate between low frequencies, so you will need to drop your sampling rate or increase the number of points in the FFT. FFT execution time is O(nlogn), so doubling the size should increase the execution time by 2.3.

You won't be able to store 2000 samples as the ATMega168 only has 1024 bytes of RAM, some of which will be required for other program variables.

FFT will give you the amplitudes of each frequency (pitch) component, so you scan through the output and find the largest peak, then measure the amplitude.

There's an ATMega FFT implementation here. 64-point execution time is 3.4 ms. I think 64-point is the biggest you're going to be able to manage as the algorithm is 16-bit, and you need 2*(N + 2*N + N/2) = 448 bytes of RAM for the input / butterfly / output buffers. For 128-point, you will therefore need 896 bytes of RAM. If you can keep your variable requirements of the rest of the prog down to 128 bytes then you might squeeze it in.
87  Forum 2005-2010 (read only) / Interfacing / Re: vibration pump from espresso machine on: August 20, 2008, 07:06:54 pm
i'd hope to use it with my radioshack .5 amp and 125 vac reed relay to control it.

That pump is 41W, so it will draw about 3A from your supply. You will likely burn out the contacts of your 0.5A relay very quickly.
88  Forum 2005-2010 (read only) / Interfacing / Re: Gravitech I2C Programmable Oscillator on: June 25, 2008, 01:14:16 am
But I just can't make sense of the values for the two "Wire.send()" commands. If I want to set the oscillator to 256 kHz, I calculate an OCT value of 7 and a DAC value of 984 in decimal. So in binary I have 0111 and 0011 1101 1000. Do I combine these to get 0111 0011 1101 1000, break it into 0111 0011 and 1101 1000 and convert to hex: 0x73 and 0xD8? Or am I totally missing the point?

You need to shift & combine the bits. Table 3 on page 8 of the data sheet will tell you where the bits need to be positioned within the 16-bit command.

declare the 16-bit value as an int with default value 0, then shift & bitwise OR the values of OCT, DAC and CNF to it

unsigned char valh, vall; // Most sig. byte & least sig byte.

unsigned int val = 0;
val |= (CNF & 0x3); // mask to 2 bits, no shift reqd
val |= ((DAC & 0x3ff) << 2); // mask to 10 bits and shift by 2 bits
val |= ((OCT & 0xf) << 12); // mask to 4 bits & shift by 12 bits

vall = val & 0xff; // mask to 8 bits (LSB)
valh = ((val & 0xff00) >> 8); // mask to top 8 bits & shift down by 8 bits (MSB)

then use valh & vall in your Wire.send() commands.
89  Forum 2005-2010 (read only) / Interfacing / Re: Tacho signal 12v to 5v ? on: May 08, 2008, 06:46:11 am
I didnt try revving it that high with the 40k resistor.

It might be worth trying so you can see if the Arduino circuitry is introducing something, or if it is a loading issue.

I agree it's quite strange - I doubt that the arduino is causing a loading issue - with the pin set to input and the internal pullup disabled it will sink only 1 uA (5.5 M equivalent input resistance). With the 50 k pullup enabled and the input driven low it will actually source 100 uA into the load.

I'd be interested to see the tacho signal on an oscilloscope, open-circuit and also with the 40k base load.

O.P. could also try a really high impedance voltage divider, like 10M / 6.8M, although it might be quite noisy, you can virtually guarantee it won't load the output.
90  Forum 2005-2010 (read only) / Interfacing / Re: Tacho signal 12v to 5v ? on: May 07, 2008, 08:01:47 am
If we select R1 to be, say 10k  R2 should be 7.1k  Closest statndard value is 6.8k.

Plugging those values (10k and 6k8) back into the first equation I wrote gives a Vout of 4.85, which is on the safe side.

So a voltage divider with resistors of 10k and 6k8 should work.  

We've already identified that anything lower than 40k on the output (300 uA) will load the tacho excessively. You could try 33k / 22k, that should work (it will give you 4.8V).
Pages: 1 ... 4 5 [6] 7