Show Posts
Pages: [1] 2 3 ... 5
1  Using Arduino / Sensors / Re: Generate/Output Gray Code from switches on: December 15, 2012, 06:31:32 pm
Not got time to go into this in detail, but here is a C prog I wrote some time ago to both encode and decode grey code. Look at the code, and you should be able to work out how to use the bits you want. There is no need for look-up tables.

Code:
/*
   Convert decimal number to Grey code and back again
*/

# include<stdio.h>

#define SIZE 32

int bits[SIZE], i; // could be chars in 8 bit machine
unsigned long num; // could be int if less than 17 bit Grey code

void main(){
  printf("\n    ");
  printf("%d",SIZE);
  printf(" bit number conversion\n");

  printf("\n Enter number     ");
  scanf("%lu",&num);

  /* converting number to binary equivalent */
  /* MSB is 1st element in array */
  for(i = 0; i < SIZE; i ++){
    bits[SIZE-1-i] = (num >> i) & 1;
  }

  /* printing binary */
  printf(" Binary           ");
  for(i = 0; i < SIZE; i ++){
    printf("%d",bits[i]);
  }

  /* in-line gray code conversion */
  for(i = SIZE-1; i > 0; i --){
    bits[i] = bits[i] ^ bits[i - 1];
  }

  /* printing gray code */
  printf("\n Gray code        ");
  for(i = 0; i < SIZE; i ++){
    printf("%d",bits[i]);
  }

  /* in-line conversion back to binary */
  for(i = 1; i < SIZE; i++){
    bits[i] = bits[i] ^ bits[i - 1];
  }

  /* reprinting binary */
  printf("\n Restored binary  ");
  for(i=0;i<SIZE;i++){
    printf("%d",bits[i]);
  }
 
   /* convert back to decimal */
  num = 0;
  for (i = 0; i < SIZE; i ++){
    num = (num<<1) | bits[i];
  }

  /* reprinting decimal number */
  printf("\n Restored decimal ");
  printf("%lu",num);
  printf("\n");
}
2  Using Arduino / Sensors / Re: IR sensor circuit problem on: December 09, 2012, 01:57:59 pm
You've shown the receiver as being a diode, but the spec sheet says it's a transistor! Is the Collector connected to +5V?

Does the output stay at zero (I'm rather expecting it does) so increase R2 to something like 1M

If it stays at or near 5V, then either it is surprisingly responsive and picking up stray IR, or you've damaged it.

What are you using as a reflector?
3  Using Arduino / Sensors / Re: How to connect current sensor to Arduino Uno? on: December 09, 2012, 01:39:27 pm
The good news is that it is possible to resolve the issue.
The bad news is that it will take a lot of time and effort.

How much the unit cost, and how much time you're prepared to spend on it will be for you to decide.
You will need a reasonable test meter, and know how to calculate current in a resistor, given the voltage.

In the first place you need to be able to generate known AC currents, and the easiest way to do this is with a low voltage transformer and some chunky resistors.

Start with, say, 1amp, and put something like 1kohm across the sensor's terminals. Close the core on the current carrying wire and see what you get. You want to end up with about 10V at the maximum current you expect to measure.

This was the easy bit.

The hard part is converting that AC voltage to a DC signal in the range 0-5V. A conventional bridge rectifier is of limited use as it will lose 1.2V straight away and give you all sorts of linearity issues. It is possible to make zero offset rectifiers with Op-Amps, but the easiest method is to use dedicated RMS-DC chips which aren't too expensive. They are also very accurate.
4  Using Arduino / Sensors / Re: SSI grey code reader on: December 09, 2012, 01:10:27 pm
Hi again,
First of all I spotted a silly mistake in the original program - corrected now.

This bit of code was part of a much larger program I wrote, that needed all the I/O that the mega provides. The result is that pin numbers and port names are quite different to the ones on the Uno. To make things easy for anyone (and me too in the future!) I've re-written it for the Uno and the code is below. I've tested it as far as possible without an actual encoder to put on it!

Code:
/*

gray code reader for Hengsler SSI 24bit multi-turn absolute encoder

I/O should be via RS224 chip

Pins chosen for Arduino Uno

Target reading bit speed 120kHz

Min reading speed for Henglser 90kHz

*/

#define SSI_CLOCK 8
#define SSI_DATA 14
#define ENCODER_LENGTH 24
#define ENCODER_SPEED 4

byte encoder[ENCODER_LENGTH + 1];
unsigned long value;


void setup(){
  pinMode(SSI_CLOCK, OUTPUT);       //  port B - 0 digital pin 8
  pinMode(SSI_DATA, INPUT);         //  port C - 0 analog pin 0
  PORTB = 1;                        //  set SSI clock idle
}


byte transfer(unsigned long &number){
  int i;
  int flag;

  noInterrupts(); 
  delayMicroseconds(50);                               //  ensure everything settled
  flag = !((PINC << 1) & 2);
  if (flag){                                           //  test for start condition
    interrupts();
  }
  else{
    for(i = 0; i <= ENCODER_LENGTH; i++){              //  overcount to read status end bit
      PORTB = 0;                                       //  set the whole port for speed
      delayMicroseconds(ENCODER_SPEED);

      PORTB = 1;                                       //  output from pin 8
      delayMicroseconds(ENCODER_SPEED);
      encoder[i] = PINC & 1;                           //  input to analog pin 0
    }
    interrupts();
    delayMicroseconds(15);                             // delay to ensure no resend
    flag = flag | (encoder[ENCODER_LENGTH] & 1);       // test for status end bit (zero)

    for(i = 1; i < ENCODER_LENGTH; i++){
      encoder[i] = encoder[i] ^ encoder[i - 1];        // convert to binary (remove these 3 lines if already binary)
    }

    number = 0;
    for (i = 0; i <ENCODER_LENGTH; i ++){
      number = (number<<1) | (encoder[i]);             // convert to unsigned long int
    }
  }
  return flag;
}


void loop(){
  bool error;

  // {code}
  error = transfer(value);
  if (error){
    if (error & 2){
      // {start fault}
    }
    else{
      // {stop fault}
    }
  }
  else{
    // {code}
  }
  // {code}
}

There are a few simplifications as there is no need to avoid certain I/O that I was using in the original project. This also makes the flag operation slightly different. but the principle remains the same.

The line:
Code:
flag = !((PINC << 1) & 2);
reads PINC (which is a very fast way to grab a block of inputs)
shifts the result one bit to the left so that bit zero (analog pin 0, now acting as digital pin 14) represents the value 2
this is then masked with 2 (the& sign) so all other pins will be ignored.
The '!' then inverts this, so that you get a '2' if the input line is not high.

The line:
Code:
flag = flag | (encoder[ENCODER_LENGTH] & 1);
looks at the last value that was put into the encoder buffer
the '& 1' is actually not necessary here as the value should only be 0 or 1, but I kept it just in case some stray values had got into the buffer. In this case we want to see if the value is 1 (input was high, which it shouldn't be)

The '|' symbol puts the two values together so that if everything is OK you end up with a value of 0. This has proved that the encoder has gone from high to low at least once so is presumably working correctly.
5  Using Arduino / Sensors / Re: SSI grey code reader on: November 29, 2012, 03:28:07 pm
Well that was some time ago!

All you really need to do is to remove the grey-binary conversion which is the four lines beginning with:

encoder[0] = encoder[0] >> 7;

You should check on the encoder you are using to see if there are any extra start and stop bits.

In my code I'm ignoring about 4 control bits at the end of the sequence. The short delay afterwards ensures that the Hengstler encoder will reset to the start. Other encoders may be different.
6  Development / Other Software Development / Re: My newest development in interfacing arduino with input hardware on: February 10, 2012, 04:27:17 pm
You are confusing the code with it's implementation. A grey code can, as you say be any number of bits, but does give an absolute reference in itself. If it is a genuine grey code there is no need for an indexing bit. This is only needed for incremental encoders - which are much cheaper. These are more commonly used for speed rather than position recognition.

I deal with absolute encoders on a daily basis, most frequently 14 and 24 bit ones. The ones I use are grey code, but the implementation I prefer is ssi (simple serial interface), in fact I actually posted reference code for this some time ago somewhere on the forums.
7  Using Arduino / Sensors / SSI grey code reader on: March 15, 2011, 06:20:36 pm
This is a very compact grey code reader for the Hengsler series of absolute encoders. It can however be easily modified for any other SSI reading situation.

Grey code doesn't suffer the reading glitches of ordinary binary as if you happen to be exactly on a transition you will only possibly get a 1 bit error.

Running speed doesn't have to be too precise but it needs to be fairly regular. That is why I disable interrupts for the actual read operation. The flag test are there to ensure that the encoder output has made at least one transition i.e. hasn't gone O/C or S/C.

Code:
/*

gray code reader for Hengsler SSI 24bit multi-turn absolute encoder

I/O should be via RS224 chip

Pins chosen for Arduino Mega

Target reading bit speed 120kHz

Min reading speed for Henglser 90kHz

*/

#define SSI_CLOCK 42
#define SSI_DATA 38
#define ENCODER_LENGTH 24
#define ENCODER_SPEED 4

byte encoder[ENCODER_LENGTH + 1];
unsigned long value;


void setup(){
  pinMode(SSI_CLOCK, OUTPUT);       //  port L - 7
  pinMode(SSI_DATA, INPUT);         //  port D - 7
  PORTL = 255;                      //  set SSI clock idle
}


byte transfer(unsigned long &number){
  int i;
  int flag;

  noInterrupts();  
  delayMicroseconds(50);                               //  ensure everything settled
  flag = !((PIND >> 6) & 2);
  if (flag){                                           //  test for start condition
    interrupts();
  }
  else{
    for(i = 0; i <= ENCODER_LENGTH; i++){              //  overcount to read status end bit
      PORTL = 0;                                       //  set the whole port for speed
      delayMicroseconds(ENCODER_SPEED);

      PORTL = 255;                                     //  output from pin 42
      delayMicroseconds(ENCODER_SPEED);
      encoder[i] = PIND;                               //  input to pin 38
    }
    interrupts();
    delayMicroseconds(15);                             // delay to ensure no resend
    flag = flag | (encoder[ENCODER_LENGTH] >> 7);      // test for status end bit (zero)
  
    encoder[0] = encoder[0] >> 7;
    for(i = 1; i < ENCODER_LENGTH; i++){
      encoder[i] = (encoder[i] >> 7) ^ encoder[i - 1]; // bit shift and convert to binary
    }
    number = 0;
    for (i = 0; i <ENCODER_LENGTH; i ++){
      number = (number<<1) | (encoder[i]);             // convert to unsigned long int
    }
  }
  return flag;
}


void loop(){
  bool error;

  // {code}
  error = transfer(value);
  if (error){
    if (error & 2){
      // {start fault}
    }
    else{
      // {stop fault}
    }
  }
  else{
    // {code}
  }
  // {code}
}
8  Using Arduino / Installation & Troubleshooting / Re: Powering Uno from regulated +5VDC Safe/Possible? on: March 05, 2011, 05:19:23 pm
See my reply here.

http://arduino.cc/forum/index.php/topic,54334.0.html

Never had a problem, and I've used lots of Arduinos, every version right back to NG.
9  Using Arduino / Installation & Troubleshooting / Re: Mega 2560- USB connection while using 5V external power on: March 05, 2011, 05:14:09 pm
This sounds suspiciously like a ground loop problem. I always power boards using an isolated DC-DC converter. At very little cost this gives you a S/C protected regulated output as well as complete isolation.
10  Using Arduino / Sensors / Re: Potentiometer with Continuous Rotation on: February 12, 2011, 08:05:43 pm
Farnell group are pretty world-wide these days
This is just under 6ukp and is 15ppr (30 if you matrix the A&B channels).

http://uk.farnell.com/alps/ec11j1520801/encoder-rotary-30ppr/dp/1656445
11  Using Arduino / General Electronics / Re: New switching regulator on it's way on: February 06, 2011, 02:42:42 pm
Looks like they added an addition LC filter on the output of this board, not suggested in the datasheet, for the better ripple spec they are getting.
Lefty
The inductor is not a filter but actually part of the switching system.

... I doubt you want to know the hoary details  smiley-razz

P.S.
You get best results when the input voltage is about twice the output voltage.
12  Using Arduino / Sensors / Re: Matrix Keypad with fewer pins? on: February 06, 2011, 02:33:47 pm
I get 8x6 key matrix plus 8bit parallel alph-numeric LCD using a bit of lateral thinking smiley

Use the 8 data pins for the LCD as the diode isolated 'drive' pins for the keypad matrix. Scan these in a tight loop between screen updates.

When not actually writing to the screen, the EN line will be low so no risk of sending obscure characters to the screen, and when you're not actually scanning the key matrix it doesn't matter how much the lines wiggle about. Also with a couple of simple arrays you can get the state of every single key simultaneously (sort of).

Program up a chip, and dedicate it to this on a breadboard with just a cheap 16MHz resonator and a few resistors and caps. I pass data in and out via direct serial connections between a couple of these and a mega.

To keep comms to the minimum everything is in single byte commands. I don't need to display top-bit characters so 128+n is top row cursor position, 160+b 2nd row cursor etc. (4x20 display). 12 is clear screen (like the old terminals). 20 is flash cursor, 21 is steady cursor and 22 is cursor off. Chars 32 to 126 are normal printables.

For the keypad side, 128+n gives row/column key-down and  192+n gives corresponding key-up. Chars 32 to 126 are kept clear so the keypad/display module can send a wake-up message.
13  Using Arduino / Installation & Troubleshooting / Re: FTDI RTS Not Working since Kernel Update (2.6.35-25) on: February 06, 2011, 11:05:05 am
I've been bitten by this one too smiley-sad

My temporary fix is to cut the pads as per manual reset/upload then solder a 100nF cap across. This makes it a lot less fiddly than trying to time the reset just right, but I have to unplug-then replug in the board every time I want to make a fresh upload - go figure!

Coincidentally, there seems to be no problem with the mega, also I've tried using a little FTDI module from RS components, connecting just the serial lines, and the RTS# line via a 100nF cap. That works perfectly (which is why it took me so long to discover there was a problem). I don't know if it's relevant but this development board of my own doesn't share the +5V with the USB module.
14  Forum 2005-2010 (read only) / Troubleshooting / Re: Very confused about timing. on: January 19, 2011, 04:08:28 am
Only if you do a subtractive comparison. Do a direct foo > bar and the wraparound gives a false result.
15  Forum 2005-2010 (read only) / Troubleshooting / Re: Very confused about timing. on: January 18, 2011, 07:47:20 pm
Well here's another fairly clean cut example. Might help.
Code:
#define ONEMINUTE 60000

unsigned long lastminute;
int minutes = 0; // either set these to starting values
int hours = 0; // or switch on at midnight!
bool running = false;

void setup(){
  // whatever else you want here
  lastminute = millis(); // should be last command in setup
}

void loop{
  if (millis() - lastminute >= ONEMINUTE){
    lastminute += ONEMINUTE;
    minutes += 1;
    if (minutes == 60){
      minutes = 0;
      hours += 1;
      if (hours == 24){
        hours == 0;
      }
    }
  }
  if (not running and hours == 8 and minutes == 30){ // just examples
    running = true;
  }
  else if (running and hours == 17 and minutes == 0){
    running = false;
  }
  if (running){
  // some function here
  }
// some other code here too
}

This will correctly handle millis()  wrap around zero and also step over any other code functions provided the overall loop time is less than 1 minute!
Pages: [1] 2 3 ... 5