Show Posts
Pages: [1] 2 3
1  Forum 2005-2010 (read only) / Syntax & Programs / Re: C++ problem with pure virtual method on: April 28, 2009, 01:26:50 am
Quote
That's really odd.  I have a Sketch with a pure virtual function...

Indeed it is. Are you compiling this with the Arduino IDE? My problem is not the DebounceButton class, but this. Sorry for taking over this thread.
2  Forum 2005-2010 (read only) / Syntax & Programs / Re: C++ problem with pure virtual method on: April 27, 2009, 04:29:13 pm
It turns out you have to define __cxa_pure_virtual() for pure virtual functions to work.

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=410870
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1207386508

And a long discussion, a good part of which I don't get:
http://www.mail-archive.com/avr-libc-dev@nongnu.org/msg01223.html
3  Forum 2005-2010 (read only) / Syntax & Programs / Re: C++ problem with pure virtual method on: April 27, 2009, 09:16:49 am
I am encountering the same error from the linker when trying to compile a sketch agains the Arduino library from SVN (pre 0016 code, i believe). All worked fine for versions up to 0014, but then they changed HardwareSerial ... CosineKitty, do you mind taking a look?

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1240829167
4  Forum 2005-2010 (read only) / Development / Re: Improved HardwareSerial on: November 14, 2009, 05:14:59 am
It seems the lib works for me. I just copied over the two files from the original post and ran the ASCII Table example -- worked just fine at 115200 baud with Arduino 0017.

What errors are you getting exactly? Does it fail when you do something specific? What board do you run it on?

As to your questions: the serial lib that comes with the distribution should be capable of much higher bauds than what you are limited to -- I'd look for the problem elsewhere smiley

The main improvement in my version is the TX buffer -- sending chunks of data is done in the background (unless the TX buffer is full), so the write() call does not block.
5  Forum 2005-2010 (read only) / Development / Re: Improved HardwareSerial on: November 11, 2009, 01:33:41 am
@retrolefty: You must have missed it, that red text is there since the original post smiley

I haven't tried to get this working under Arduino 17 -- I never managed to get the 17 release working under my new shiny laptop with Arch Linux x86_64.

I'll give it another try when I have a spare minute. Nice to see that people are interested smiley
6  Forum 2005-2010 (read only) / Development / Re: Improved HardwareSerial on: July 16, 2009, 10:18:28 am
@rglenn: I agree. Adding the *Async() functions is not a good idea.

What's wrong with making the transmitter asynchronous? Copying data into the buffer is a small price to pay compared to the other benefits.

To me, both RX and TX should be asynchronous, the RX buffer size should be decreased (128 bytes is waaay more than needed in 99% of the cases), TX buffer should be 32 or 64 bytes by default.

If altering the existing HardwareSerial is such a big problem, why don't you guys just make an alternative and add it to the distribution? Given the choice, user's will pick what's best for them. Fact is, the current "official" implementation does not work for me, and many others, I believe.
7  Forum 2005-2010 (read only) / Development / Re: Improved HardwareSerial on: May 19, 2009, 07:06:23 am
0016?! Didn't even cross my mind!

What I am proposing is to think about introducing some of the improvements/features, mainly the TX buffer. This alone is too much of a change to even consider it feasible for the upcoming release, but let's start a discussion about it -- maybe we can have it by 0020, no?

What about the other changes? head and tail in the ring_buffer are still int-s? Is anyone using buffers larger than 128 bytes? Even if so, why not 'unsigned int'? mekon83 is the person who pointed out these issues first, and his implementation was much faster with minimal changes in the code that would have been completely unnoticeable to almost all users. Sure, most of them wouldn't have noticed the improved performance either ...

As to portability: my version should run fine at any clock speeds given BAUDs in a reasonable range, and can be made to run on all MCUs. Once again, the latter was intentionally left out.
8  Forum 2005-2010 (read only) / Development / Re: Improved HardwareSerial on: May 19, 2009, 12:23:11 am
Quote
Correct operation and reliability are two.

I've tested as much as I could, and there are hundreds of users here -- these can easily be achieved with a combined effort.

Quote
Portability (across arduino processors and clock speeds) is another.

Portability was intentionally left out, as I have no means of testing it. Again, if there's a will, there's a way.

mekon83 is right.

Did anyone try the code at all? Can you do some benchmarks/tests?
9  Forum 2005-2010 (read only) / Development / Improved HardwareSerial on: May 16, 2009, 04:42:15 am
Hi All,

I am sure many people have seen the shortcomings of HardwareSerial and came up with their own versions. So here's yet another one. The public interface is the same as the original, your sketches should work with the new one just as with the old one.

Changes/improvements:

 * Fully asynchronous operation, uses both RX and TX buffers
 * Buffer sizes are individually configurable
 * Tried to optimize the code for size and memory usage

The library only supports Arduinos with ATmega168 or ATmega328. I don't have the Mega, or an old arduino with ATmega8, so I cannot test the lib for these MCUs.

I'd be happy if you take a look at the code and feed my back a little.

I can modify it to work with all arduinos if there's interest. I'd be especially happy to see some of the improvements in the official lib -- the TX buffer can speed things up a lot.


Code:
/*
  HardwareSerial.h - Improved HardwareSerial library for Arduino
  Copyright (c) 2009 Kiril Zyapkov.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef HardwareSerial_h
#define HardwareSerial_h

#include <inttypes.h>

#include "Print.h"

// Define the amount of tolerance upon which x2 will be enabled, in percent
#define BAUD_TOL 2

// Both buffers must be powers of 2, up to 128 bytes
// Keep in mind the memory limits of the MCU!!
#define USART_RX_BUFFER_SIZE   16
#define USART_TX_BUFFER_SIZE   32

// There were other ways of implementing the ring buffers that I thought of,
// that avoid defining 2 separate struct's for the same thing:
//
//  * allocating memory for the buffers using malloc() at runtime
//      not sure how 'dynamic' memory management will work on the micro
//  * using separate variables, not packing the buffers into structs
//      structs are much neater
//  * defining a single macro for buffer size
//      both buffers would need to have the same size
struct rx_ring_buffer {
    uint8_t buffer[USART_RX_BUFFER_SIZE];
    volatile uint8_t head;
    volatile uint8_t tail;
};

struct tx_ring_buffer {
    uint8_t buffer[USART_TX_BUFFER_SIZE];
    volatile uint8_t head;
    volatile uint8_t tail;
};


class HardwareSerial : public Print
{
  private:
    rx_ring_buffer *_rx_buffer;
    tx_ring_buffer *_tx_buffer;

  public:
    HardwareSerial(rx_ring_buffer *, tx_ring_buffer *);
    void begin(unsigned long);
    void write(uint8_t);
    void flush(void);
    uint8_t available(void);
    uint8_t read(void);

};

extern HardwareSerial Serial;

#endif


Code:
/*
  HardwareSerial.cpp - Improved HardwareSerial library for Arduino
  Copyright (c) 2009 Kiril Zyapkov.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  
*/
#include <avr/io.h>
#include <avr/interrupt.h>

#include "HardwareSerial.h"

#define USART_RX_BUFFER_MASK (USART_RX_BUFFER_SIZE-1)
#define USART_TX_BUFFER_MASK (USART_TX_BUFFER_SIZE-1)

#if ( USART_RX_BUFFER_SIZE & USART_RX_BUFFER_MASK )
#    error RX buffer size is not a power of 2
#endif
#if ( USART_TX_BUFFER_SIZE & USART_TX_BUFFER_MASK )
#    error TX buffer size is not a power of 2
#endif

#ifndef BAUD_TOL
#   define BAUD_TOL 2
#endif

// both buffers are static global vars in this file. interrupt handlers
// need to access them
static rx_ring_buffer rx_buffer;
static tx_ring_buffer tx_buffer;

/**
 * Initialize the USART module with the BAUD rate predefined
 * in HardwareSerial.h
 *
 * This may implement passing addresses of registers, like the HardwareSerial
 * class from the Arduino library, but that's not necessary at this point.
 *
 */
HardwareSerial::HardwareSerial(rx_ring_buffer *rx_buffer_ptr, tx_ring_buffer *tx_buffer_ptr) {

    _rx_buffer = rx_buffer_ptr;
    _tx_buffer = tx_buffer_ptr;

    // Allocate memory for the rx and tx buffers
    // That is, if the structs contain pointers to the actual buffer
    // arrays. I'm going for defining 2 separate struct's and allocating them
    // statically.
//    _rx_buffer->buffer = (uint8_t *)malloc(USART_RX_BUFFER_SIZE);
//    _tx_buffer->buffer = (uint8_t *)malloc(USART_TX_BUFFER_SIZE);
}

void HardwareSerial::begin(unsigned long baud) {
    // taken from <util/setbaud.h>
    uint8_t use2x = 0;
    uint16_t ubbr =  (F_CPU + 8UL * baud) / (16UL * baud) - 1UL;
    if ( (100 * (F_CPU)) > (16 * (ubbr + 1) * (100 * ubbr + ubbr * BAUD_TOL)) ) {
        use2x = 1;
        ubbr = (F_CPU + 4UL * baud) / (8UL * baud) - 1UL;
    }

    UBRR0L = ubbr & 0xff;
    UBRR0H = ubbr >> 8;
    if (use2x) {
        UCSR0A |= (1 << U2X0);
    } else {
        UCSR0A &= ~(1 << U2X0);
    }

    // Flush buffers
    _tx_buffer->head = _tx_buffer->tail = 0;
    _rx_buffer->head = _rx_buffer->tail = 0;

    UCSR0B |= (1<<TXEN0);  // Enable Transmitter
    UCSR0B |= (1<<RXEN0);  // Enable Reciever
    UCSR0B |= (1<<RXCIE0); // Enable Rx Complete Interrupt
}

void HardwareSerial::write(uint8_t data) {
    // Calculate new head position
    uint8_t tmp_head = (_tx_buffer->head + 1) & USART_TX_BUFFER_MASK;

    // Block until there's room in the buffer
    // XXX: this may block forever if someone externally disabled the transmitter
    //      or the DRE interrupt and there's data in the buffer. Careful!
    while (tmp_head == _tx_buffer->tail);

    // Advance the head, store the data
    _tx_buffer->buffer[tmp_head] = data;
    _tx_buffer->head = tmp_head;

    UCSR0B |= (1<<UDRIE0); // Enable Data Register Empty interrupt
}

void HardwareSerial::flush(void) {
    // Not sure if disabling interrupts is needed here, but let's be on
    // the safe side
    // disable interrupts
    uint8_t oldSREG = SREG;
    cli();
    _rx_buffer->head = _rx_buffer->tail;
    // Re-enable interrupts
    SREG = oldSREG;
}

/**
 * Returns the number of bytes in the RX buffer
 *
 */
uint8_t HardwareSerial::available(void) {
    //    return (_rx_buffer->head + USART_RX_BUFFER_SIZE - _rx_buffer->tail) % USART_RX_BUFFER_SIZE;
    // stupid compiler ...
    uint16_t tmp = (_rx_buffer->head + USART_RX_BUFFER_SIZE - _rx_buffer->tail);
    tmp %= USART_RX_BUFFER_SIZE;
    return (uint8_t)tmp;
}

/**
 * Returns a byte from the RX buffer, or NULL if none are available
 */
uint8_t HardwareSerial::read(void) {
    uint8_t tmp_tail, tmp_data;

    // disable interrupts
    uint8_t oldSREG = SREG;
    cli();
    if (_rx_buffer->head == _rx_buffer->tail) {
        // Better that than block the code waiting for data. Users should call
        // available() first
        tmp_data = -1;
    } else {
        tmp_tail = (_rx_buffer->tail +1) & USART_RX_BUFFER_MASK;
        tmp_data = _rx_buffer->buffer[tmp_tail];
        _rx_buffer->tail = tmp_tail;
    }
    // Re-enable interrupts
    SREG = oldSREG;

    return tmp_data;
}

/**
 * Receive handler
 */
ISR(USART_RX_vect) {
    uint8_t data = UDR0;
    uint8_t tmp_head = (rx_buffer.head + 1) & USART_RX_BUFFER_MASK;
    if (tmp_head == rx_buffer.tail) {
        // buffer overflow! for now, the strategy is to discard a byte off
        // the queue, so that the fresh data can be written. Probably an overflow
        // flag should be raised somewhere ...
        // http://c2.com/cgi/wiki?CircularBuffer
        rx_buffer.tail = (rx_buffer.tail + 1) & USART_RX_BUFFER_MASK;
    }
    rx_buffer.buffer[tmp_head] = data;
    rx_buffer.head = tmp_head;
}

/**
 * Data Register Empty Handler
 */
ISR(USART_UDRE_vect) {
    if (tx_buffer.head == tx_buffer.tail) {
        // Buffer is empty, disable the interrupt
        UCSR0B &= ~(1<<UDRIE0);
    } else {
        tx_buffer.tail = (tx_buffer.tail + 1) & USART_TX_BUFFER_MASK;
        UDR0 = tx_buffer.buffer[tx_buffer.tail];
    }
}

HardwareSerial Serial(&rx_buffer, &tx_buffer);

To give it a try, replace hardware/cores/arduino/HardwareSerial.{cpp,h} with the ones listed above. Keep backups of the originals!
10  Forum 2005-2010 (read only) / Development / Re: Arduino on Eclipse : Quick and dirty tutorial on: May 22, 2009, 09:29:19 am
You could use a Makefile of your own. Uncheck "Generate Makefiles automatically" in the project options and use the hardware/cores/arduino/Makefile. It may take some tweaking to have it play nicely.

I personally prefer copying the core lib into the project, so that I can modify it. I get rid of main.cxx and use a more generic build process.
11  Forum 2005-2010 (read only) / Development / Re: Detect voltage or resistance drops?Like multimeter on: May 16, 2009, 04:51:04 am
The micros have an Analog Comparator module -- this can be used to compare voltages between input pins. See the datasheet of the MCU.

As for resistance measurement -- that cannot be done directly. You'll need a voltage source applied on the resistance you want to measure and again measure the voltage, either using the ADC or the comparator. Some analog circuitry may be required for this, for example:

http://en.wikipedia.org/wiki/Wheatstone_bridge

What exactly are you trying to achieve?
12  Forum 2005-2010 (read only) / Development / Re: Arduino0015+Eclipse problems on: June 22, 2009, 03:47:31 pm
> Do I then delete the two lines that set MMCU and F_CPU in the makefile, or will this override them?

Variables on the command line will override the ones in the file. If you leave the Makefile as-is you can do the build from a terminal. It's always a good idea to keep this option available, if anything should happen to your Eclipse installation. Plus, you can carry a tarball of your project around and it will probably compile in any environment that has the required tools.

As to automagically including/compiling libraries -- there must be a way to add these with the wildcard function and other text-manipulating functions. I never tried too hard to do that, since I always copied only the library source files that I need into the project and often had to modify them for one reason or another.

I haven't played with Arduino lately, I'm playing with an Android G2 now smiley-grin. I'll try to find some time and modify the Makefile to support that. If you want, you can take a look at the GNU Make manual and try that yourself

http://www.gnu.org/software/make/manual/make.html
13  Forum 2005-2010 (read only) / Development / Re: Arduino0015+Eclipse problems on: June 21, 2009, 07:20:50 am
You're welcome, I'm glad you find it useful.

The target for the 328 is atmega328p, you omitted the 'p' at the end, hence the error.

I've actually found a way to feed these settings from Eclipse to the make process, so you don't have to modify the Makefile every time you change your board. Go to project Properties -> C/C++ Build -> Behaviour (Tab) and set the "Build (incremental build)" string to:

Code:
MMCU=${AVRTARGETMCU} F_CPU=${AVRTARGETFCPU} all

Now, when you set the target hardware and clock speed in Eclipse they will be automatically passed to the compiler.
14  Forum 2005-2010 (read only) / Development / Re: Arduino0015+Eclipse problems on: May 22, 2009, 04:28:26 am
Yes, I used the Makefile from the distribution as a reference (and quite a few others, for that matter) but wrote mine from scratch. (Just as with HardwareSerial, I feel I get a much deeper grasp of the subject when I do it that way.) Makefiles are a punishment! but I'll take a deeper look and see if I can adapt it to integrate my changes.
15  Forum 2005-2010 (read only) / Development / Re: Arduino0015+Eclipse problems on: May 21, 2009, 05:46:14 pm
I don't know if anyone is interested at all -- it seems not too many people use Eclipse to write for Arduino. Nevertheless, I managed to write a Makefile (oh, the pain!) that replicates the build process of the official ide and even adds some additional improvements.

Here's a quick writeup:

http://lz3060.wordpress.com/2009/05/21/avr-makefile-first-attempt/

The advantages of my setup (vs. the one described in the Playground) are that you can modify core libraries and have them automatically recompiled with the next build. It also adds all .o files to the object archive, allowing the linker to do it's magical garbage collecting everywhere. I am getting even smaller builds with this than with the official IDE!

LMK if you find it useful or need more details on how it works.
Pages: [1] 2 3