Show Posts
Pages: 1 [2] 3 4 ... 6
16  Using Arduino / Programming Questions / Re: A function to handle multiple datatypes on: November 02, 2012, 02:20:39 am
How do templates work? I have tried googleing but I can't seem to find a nice concise guide.
17  Using Arduino / Programming Questions / Re: A function to handle multiple datatypes on: November 02, 2012, 02:13:21 am
Quote
That's so sad, I can't tell you.

Apologies, Nick. Those were actually the errors I got when I tried to compile my sketch with the EEPROMWriteAnything function in it. Word for word, copied and pasted. I just didn't make it clear. Sorry. Just finished a night shift.

So, which approach should I use? Passing a void pointer or writing multiple functions?

Chris
18  Using Arduino / Programming Questions / A function to handle multiple datatypes on: November 02, 2012, 12:25:16 am
Hello all,

If there any way that I can write a function that will accept multiple datatypes?
This is what I am trying to do:
I want a function that I can pass either a string of characters or an integer or an object and it will treat it as a stream of bytes so that I can write them out to the serial port one byte at a time. The function will also include things like byte stuffing, but I can deal with that later.

I remember that there was an EEPROMWriteAnything function that used template <class> and things like that but I can't figure out how to adapt it to my needs. I tried and all I get is errors; things like "expected ',' or '...' before '&' token" and "error: ISO C++ forbids declaration of 'T' with no type"

Help?
19  Community / Exhibition / Gallery / Re: WiFi Spectrum Analyzer on: September 30, 2011, 10:11:28 am
Hi folks,

I was looking to build a 2.4GHz analyser and I stumbled upon this thread. Thankyou for your hard work and I would like to share a couple of changes I have made which allowed me to increase the fast scan scanning speed by a wopping 54.5 times!

First change: Switch the way the data is fed to the LCD screen from ShiftOut to SPI. Simply move the wires from pin 4 to pin 11, and pin 3 to pin 13. Then change
Code:
shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
in LcdWrite to
Code:
SPI.transfer(data)
This resulted in a 15x speed increase, taking the frame rate from 0.36fps to 5.75fps

Second change: The LcdWrite function uses bitWrite() to assert the chip select line instead of digitalWrite(), so I changed RADIO_Read() and RADIO_Write() to use bitWrite(). Pin 8 on the arduino relates to PORTB, bit 0, so I changed the functions to become
Code:
// Read data from radio module
unsigned char rssi::RADIO_Read(unsigned char address){
  bitWrite(PORTB, 0, 0) ;
  unsigned char value;
  SPI.transfer(address);
  value = SPI.transfer(0x00);
  bitWrite(PORTB, 0, 1) ;
  return value;
}

// Write data to radio module
void rssi::RADIO_Write(unsigned char address, unsigned char value){
  // Enable module
  bitWrite(PORTB, 0, 0) ;
  // Send data
  SPI.transfer(0x80|address);
  SPI.transfer(value);
  // Disable module
  bitWrite(PORTB, 0, 1) ;
}
This resulted in a much smaller speed increase, of just over quarter of a frame a second but any increase is a good increase!

Finally I implemented the by-pixel line update method put forward by robtillaart and this resulted in a further increase from 6.06fps to 19.61fps! A wopping 54.47x speed increase.

You might be wondering why I need such a fast refresh rate, but I am using it to monitor RC aircraft transmitters and the FrSky system I am using hops frequency so fast that if the frame rate is too slow then the odds of scanning a given frequency at the time the TX is transmitting on it is very slim.

I hope that my mods will prove usefull to someone else!

Thank you so much for the hard work that you guys put in on this.

Chris
20  Using Arduino / Programming Questions / Re: Annoying compliler errors on: March 30, 2011, 11:43:44 pm
ignore that last post.

Fixed it. smiley-red
21  Using Arduino / Programming Questions / Re: Annoying compliler errors on: March 30, 2011, 11:41:47 pm
Excellent. Thanks, Lefty.

However now I have a further problem. The code is now in an .h tab (and so are various other bits in the project) but now it is trying to tell me I am redefining things that I am defining for the first time.

errors:
Code:
In file included from version0_6.cpp:18:
storage.h:5: error: redefinition of 'Sd2Card card'
storage.h:5: error: 'Sd2Card card' previously declared here
storage.h:6: error: redefinition of 'SdVolume volume'
storage.h:6: error: 'SdVolume volume' previously declared here
storage.h:7: error: redefinition of 'SdFile root'
storage.h:7: error: 'SdFile root' previously declared here
storage.h:8: error: redefinition of 'SdFile file'
storage.h:8: error: 'SdFile file' previously declared here
storage.h:10: error: redefinition of 'template<class T> int file_writeAnything(const T&)'
storage.h:10: error: 'template<class T> int file_writeAnything(const T&)' previously declared here
storage.h:19: error: redefinition of 'template<class T> int file_readAnything(T&)'
storage.h:19: error: 'template<class T> int file_readAnything(T&)' previously declared here
storage.h: In function 'boolean setupStorage()':
storage.h:30: error: redefinition of 'boolean setupStorage()'
storage.h:30: error: 'boolean setupStorage()' previously defined here
storage.h: In function 'void getConfigData()':
storage.h:85: error: redefinition of 'void getConfigData()'
storage.h:85: error: 'void getConfigData()' previously defined here
storage.h: In function 'void updateConfigData()':
storage.h:102: error: redefinition of 'void updateConfigData()'
storage.h:102: error: 'void updateConfigData()' previously defined here
storage.h: In function 'void storeData()':
storage.h:115: error: redefinition of 'void storeData()'
storage.h:115: error: 'void storeData()' previously defined here

and the code:
Code:
#define CD_PIN 3
#define CARDSPEED SPI_HALF_SPEED    //this can be set to SPI_FULL_SPEED if you want

//SD Card
Sd2Card   card;
SdVolume  volume;
SdFile    root;
SdFile    file;

template <class T> int file_writeAnything(const T& value)
{
  const byte* p = (const byte*)(const void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++)
    file.write(*p++);
  return i;
}

template <class T> int file_readAnything(T& value)
{
  byte* p = (byte*)(void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++)
    *p++ = file.read();
  return i;
}



boolean setupStorage()
{
  if (!enable_storage) {
    messageln ("Logger Disabled");
    return false;
  }
  pinMode(CD_PIN, INPUT);
  digitalWrite(CD_PIN, HIGH);
  //look for a card
  if (digitalRead(CD_PIN)) {
    error ("SD Card: There is no SD card installed");
    enable_storage = false;
    return false;
  }
  //try and initalise the card
  if (!card.init(CARDSPEED,9)) {
    error("SD Card: Failed to initalise card");
    enable_storage = false;
    return false;
  }
  else {
    messageln ("SD Card: SD Card Initalised");
  }
  if (!volume.init(&card)) {
    error("SD Card: Failed to initalise volume");
    enable_storage = false;
    return false;
  }
  else {
    messageln ("SD Card: Volume initalised");
  }
  if (!root.openRoot(&volume)) {
    error ("SD Card: Failed to initalise Root");
    enable_storage = false;
    return false;
  }
  else {
    messageln ("SD Card: Root initalised");
  }
  message("SD Card: Card Type - ");
  switch(card.type()) {
  case SD_CARD_TYPE_SD1:
    messageln("SD1");
    break;
  case SD_CARD_TYPE_SD2:
    messageln("SD2");
    break;
  case SD_CARD_TYPE_SDHC:
    messageln("SDHC");
    break;
  default:
    messageln("Unknown");
  }
}

void getConfigData()
{
  if (!enable_storage) return;
  if (!file.open(&root, "config.alt", O_READ)) { //file doesn't exists
    if (file.open(&root, "config.alt", O_CREAT | O_APPEND | O_WRITE)) {
       file_writeAnything(configData);
       file.close();
       messageln("Created new config data file");
    }
   } else {
     file_readAnything(configData);
     file.close();
     messageln("Loaded config data");
   }
 
}

void updateConfigData()
{
  if (!enable_storage) return;
 
  SdFile::remove(&root, "config.alt");
      if (file.open(&root, "config.alt", O_CREAT | O_APPEND | O_WRITE)) {
       file_writeAnything(configData);
       file.close();
       messageln("Updated config data");
    }
 
}

void storeData()
{
  if (!enable_storage) return;
  char name[12];
  sprintf(name, "flt%05d.csv", flight_number);
  if (!file.open(&root, name, O_CREAT | O_APPEND | O_WRITE)) {
    error("Unable to open file");
  }
  file.print(millis());
  file.print(",");
  file.print(altitude);
  file.print(",");
  file.print(filter.x);
  file.println();
  if (file.writeError) {
    error("File write failed");
    enable_storage = false;
  }
  if (!file.close()) {
    error("File close failed");
    enable_storage = false;
  }
}



22  Using Arduino / Programming Questions / Annoying compliler errors on: March 30, 2011, 11:25:19 pm
I am getting this error:
Code:
sketch_mar31a:-1: error: expected ',' or '...' before '&' token
sketch_mar31a:-1: error: ISO C++ forbids declaration of 'T' with no type
sketch_mar31a:-1: error: 'T' was not declared in this scope
sketch_mar31a:-1: error: 'value' was not declared in this scope
sketch_mar31a:9: error: 'template<class T> int file_readAnything(T&)' redeclared as different kind of symbol
sketch_mar31a:-1: error: previous declaration of 'int file_readAnything'

from this code
Code:
template <class T> int file_writeAnything(const T& value)
{
  const byte* p = (const byte*)(const void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++)
    //file.write(*p++);
  return i;
}

template <class T> int file_readAnything(T& value)
{
  byte* p = (byte*)(void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++)
   // *p++ = file.read();
  return i;
}

void setup()
{
 
}

void loop()
{
 
}

The above code is a segment from a larger project and it used to work before I upgraded to the latest IDE.
Struggleing here.

I know there is no code in the setup and loop functions, but it should still complie without any problems.
Any ideas?
23  Forum 2005-2010 (read only) / Troubleshooting / Re: Interrupts and stepper motor advice needed. on: March 30, 2010, 09:18:56 am
The main problem is that Serial.print(); really isn't up to the job, as it takes way too long to output the data and so it is missing the next 'x' interupts. What you really need to is create an output using the compare A or B register and use an oscilloscope to measure the time bewteen pulses. I understand that most people don't have oscilloscopes lying round; I was lucky enought to inherrit one from my Dad.

Try this code:
Code:

ISR(TIMER1_COMPA_vect)  // Timer-1 OC1A Match interrupt handler
{
  //No need to do anything here other than change the pause between pulses
 // by changing the value of OC1A
};

void setup()
{
  Serial.begin(9600);
  delay(50);
  TCCR1A = B0011001;    
  TCCR1B = B0100010;
  TCCR1C = B0000000;
  TIMSK1 = B0000010;  
  ITFR1  = B0000010;
  OCR1A = 4000;      //Pause between pulses in us
  OCR1B = 100;       //Pulse Length in us
  TCNT1 = 0;
  pinMode(10, OUTPUT); //this produces a pulse on pin 10;
  
}

void loop(){}

The way this differs from yours is that it uses phase and frequency correct PWM mode to generate the pulses, rather than 'normal' mode. It also uses the compare 'B' register to output a pulse on pin 10 (you can't change this, as it is hardwired).

The length of the pause between pulses is determined by the value of compare register A. In this PWM mode the counter counts both up and down, so a 'top' value of 4000 will result in a total count of 8000 between pulses, at 0.5us per 'tick' that gives you a pause bewteen pulses of 4000us.

The great thing about this mode, is that compare register A is double buffered, and updates when the timer reaches 0, making it very easy to control the length of the pulse. You can use the OC1A interrupt vector to change the value of OC1A.

The length of the pulse is determined by the value of compare register B, a value of 10 would result in a 10us pulse. If you check the datasheet for your stepper driver it shoudl tell you the minimum pulse length required to induce a step.

The 'direction' of the pulse can be changed by changing the value of TCCR1A to B0010001

I hope most (any) of that makes sense.

Chris
24  Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega on: April 19, 2010, 12:52:12 pm
Ah yes, I see now.
Well that will teach me to open mouth before engaging brain won't it.

It states that Servo (the old one) won't work on the mega. I assume this is because of the different timers on the Mega. I would look at the datasheet, but I am at work and I don't think my iPhone will like a 25mb+ PDF!

Thanks for putting me right.
25  Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega on: April 19, 2010, 10:30:55 am
You are quite right, I was not looking at the 0016 version. I only started with arduino at version 0017 and didn't realise that the servo library was different prior to that. Noobie mistake there on my part

chris
26  Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega on: April 19, 2010, 07:03:54 am
Quote
Chris, note that the Servo library supplied with Arduino version 0016 does run one or two servos on timer1 without interrupts

I have had a look at the Servo.c file and it look to me like the servo library always uses interrupts to handle the servos, regardless of which timer it is using. If this is not the case, could you point me to the section of code that does this as I am interested in how it decides to use an intrrupt or not.

In the mean time I have knocked up some code that will position a servo using timer1 without any interrupts whatsoever.

Code:
/**
 * Precision servo positioning.
 *
 * Uses timer1 in phase and frequency correct PWM mode
 * Doesn't use interrupts, so should be immune to interrupt issues.
 *
 * Chris Parish 2010
 *
 */


//The standard timings for servos are 1.5ms for center, 1ms and 2ms for the full extents of travel
//however, most modern servos can operate an extended range, this can be as wide as 0.5ms to 2.5ms
//Consult the documentation for your servo for further details
#define SERVO_LOWER_LIMIT  1000
#define SERVO_UPPER_LIMIT  2000
#define SERVO_CENTER       1500

//Set your servo travel here. In standard mode most servos travel approx 90 degrees (45 either side of center)
#define SERVO_ANGLE_LOWER  0    
#define SERVO_ANGLE_UPPER  90

const int servo = 9;
int angle;

void setup()
{
  //Set up the timer------------------------
  //TCCR1A register
  TCCR1A = 0; //clear the register completly
  TCCR1A |= _BV(COM1A1) | _BV(COM1B1);  //set the required bits

  //TCCR1B register
  TCCR1B = 0; //clear the register completley  
  TCCR1B |= _BV(WGM13) | _BV(CS11);  //set the required bits

  //TCCR1C register
  TCCR1C = 0; //clear the register completley

  //Set the top limit - Complete frame length
  ICR1 = 20000;  //In this mode (assuming that you are running at 16mhz) The values are set in microseconds.

  //Set the output compare registers which dictate the servo position
  OCR1A = SERVO_CENTER; //1.5ms pulse, center the servo
  OCR1B = SERVO_CENTER; //1.5ms pulse, center the servo

  //Set pins 9 and 10 to output the waveform to the servos
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  
  Serial.begin(9600);

}

void setServoAngle(int servo, int angle)
{
  //constrain the angle measurement
  angle = constrain(angle, SERVO_ANGLE_LOWER, SERVO_ANGLE_UPPER);
  //convert the angle measurement into a pulse length
  angle = map(angle, SERVO_ANGLE_LOWER, SERVO_ANGLE_UPPER, SERVO_LOWER_LIMIT, SERVO_UPPER_LIMIT);

  //write the angle to the appropreate servo output (1 or 2  -aka- 9 or 10)
  if (servo == 1 || servo == 9)
  {
    OCR1A = angle;
  }
  else if (servo == 2 || servo == 10)
  {
    OCR1B = angle;
  }
}

int getServoAngle(int servo)
{
  int pulse;
  int angle;
    if (servo == 1 || servo == 9)
  {
    pulse = OCR1A;
  }
  else if (servo == 2 || servo == 10)
  {
    pulse = OCR1B;
  }
  return map(pulse, SERVO_LOWER_LIMIT, SERVO_UPPER_LIMIT, SERVO_ANGLE_LOWER, SERVO_ANGLE_UPPER);

}
There is no loop() in the code above, feel free to out your own in!
It does work, I tried it.

Chris
27  Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega on: April 16, 2010, 10:33:58 pm
Just had a quick look, and SoftwareSerial doesn't use interrupts at all. NewSoftSerial uses timer0 so you could almost certainly implement a precise servo controller using timer1.

If you are interested I could knock up some code.

Chris
28  Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega on: April 16, 2010, 10:25:05 pm
Just an idea, and I am perfectly prepared to be shot down in flames here, but would this help?

You said that you are using the servo to control a tracking antenna, so from that I presume that you are using just one servo.
Assuming, and it is a big assumption, that none of the other libraries you are using are using timer1, the 16bit timer, you could very easily write a routine to generate the servo PPM train using Phase and Frequency correct PWM mode on the timer in conjunction with the waveform generator to output the pulse train on pins 9 or 10 with a resolution of 1microsecond. this would not require any interrupts and because it is a hardware solution unless something stops the timer for some reason it will continue to run regardless of what the CPU is doing.
Basically, if you take the servo handling away from the interrupts then it is not likely to jitter like you have been experiencing.

Chris
29  Forum 2005-2010 (read only) / Troubleshooting / Re: inverting a pwm signal on: March 30, 2010, 11:22:17 am
I was wondering, I haven't had much experience driving DC motors. I gather that you are using PWM, but how are you controlling speed? is it done by simply increasing the duty cycle, or can it be done by changing the frequency of the pulse, like you would with a stepper motor?
Sorry if these are daft questions, but I really don't know anything about DC motors!

Chris
30  Forum 2005-2010 (read only) / Troubleshooting / Re: inverting a pwm signal on: March 30, 2010, 11:02:06 am
No problem. Glad I could help.

Chris
Pages: 1 [2] 3 4 ... 6