Thread: Scaling query

  1. #1
    Registered User
    Join Date
    Sep 2014
    Posts
    6

    Scaling query

    Hi,

    I would like to read a 8 bit ADC reading (00 to FF). I would like to then represent this reading on a 3 seven segment displays (0 to 100). I would like some guidance of how my c programme would look. Would I need to tabulate the entire ADC reading for each individual step ie 0x00 = 0, 0x7f=50 & 0xff=100 etc? Just trying to understand how I would scale this.

    Thanks in advance.

    clueless

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,557
    I would like some guidance of how my c programme would look.
    What have you tried? How you "print" the number to your displays will depend on how those displays are configured, and addressed. This is not a "standard" system so many of the aspects of your system will need to be shown and remember every C program starts with a main() function.


    Jim

  3. #3
    Registered User
    Join Date
    Sep 2014
    Posts
    6
    I'm using a DDM4 lcd display.This is a SPI display that requires 32 bits to represent 3 digits.I am just looking for the principles of how to acheive this.I currently just have a adc reading that I need to manipulate.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Do you know C? Do you know in what format the "DDM4" display expects the 32 bits to be? What platform will this run on? Is there an operating system? Is it embedded? You're awfully thin on details and effort at this point. Nobody here will be able to answer your questions until you back them up with some information.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  5. #5
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Assuming Lascar DDM4 module, both the pinout and the format of the 32-bit messages are shown in the datasheet.

    Most microcontrollers are big-endian (most significant bit and byte first), with 8-bit SPI buses that clock out the most significant bit first. If you clock out the 32 bits in the memory order, i.e. the byte at the lowest address first, the byte at the highest address last, the bits in the 32 bit word are
    Code:
          05          13          21          29
       06    04    14    12    22    20    30    28
          07          15          23          31
       01    03    09    11    17    19    25    27
    00    02    08    10    16    18    24    26
    where 00 corresponds to the least significant bit (value 0x00000001), and 31 the most significant bit (value 0x80000000) in the 32-bit word.

    If you use an USB dongle (USB-to-SPI with a few extra I/O pins), the situation is basically the same, except you need to consider the specifications on the dongle instead of on your computer. (Just because your computer is a little-endian machine, does not mean the dongle pushes multibyte data out in little-endian byte order, or even that it pushes bits in a byte in a little-endian order. They usually do not, although some can be configured somewhat.)




    Anyway, you have several options. The easiest one requires 256 32-bit words, or 1024 bytes of ROM (flash), and I bet you can spare that.

    Instead of worrying about numbers and values, think of the ADC giving you just an 8-bit code, that selects one of the 256 possible 32-bit images to be displayed on the LCD. The fact that the 32-bit image encodes a numeric value, is irrelevant here.

    Using the above bit pattern, you create a table of the 256 possible LCD element pictures you wish to show. (I'd use Linux command-line tools to achieve this, but your mileage may vary.) Encode the values into an uint32_t (u32 in some libraries; I use GCC) array; say static const uint32_t lcd_image[256] = ...; , and you are almost there. Add the ADC-reading logic, sending the correct 32-bit image to the DDM4, and pulse the LOAD line for at least 175 nanoseconds, and you should have a working unit.

    (175 ns is one clock cycle at up to 5.7 MHz, two clock cycles at up to 11.4 MHz, four at up to 22.8 MHz, six at up to 34.2 MHz, seven at up to 40 MHz, nine at up to 51 MHz, eleven at up to 62.8 MHz, and so on. The datasheet indicates the pulse can be longer, no maximum is listed.)




    If you intend to do software calibration, that is, have a button or something that causes the current ADC value to be considered 0, and another that causes the current ADC value to be considered 100, then you do need to do some math first:
    Code:
    readout = ((int16_t)100 * (int16_t)(ADC - min)) / (int16_t)(max - min);
    where ADC is the value (0 to 255, inclusive) read from the ADC, min is the ADC value corresponding to zero readout, and max is the ADC value corresponding to 100 readout. This truncates the result, instead of doing correct rounding.

    Note that you should pre-clamp (using two if clauses) the ADC to the min .. max range, to avoid strange readouts:
    Code:
    if (min < max) {
        if (ADC < min) ADC = min;
        if (ADC > max) ADC = max;
    } else
    if (min > max) {
        if (ADC > min) ADC = min;
        if (ADC < max) ADC = max;
    } else
        ADC = min;
    The above test may look like overly complicated (most would think that the second and third lines suffice!), but written this way, your display will work right even if the "zero" has higher ADC value than "one hundred".

    If you want rounding, precalculate
    Code:
        int16_t half = (max - min) / 2;
    whenever min and/or max changes, and then use
    Code:
    readout = (half + (int16_t)100 * (int16_t)(ADC - min)) / (int16_t)(max - min);
    to get normal rounding. Because readout is always nonnegative, and ADC is clamped to the valid range, adding half the divisor before the division moves the truncation point half a unit upwards, thus leading to correct rounding.

    Finally, you can use readout again as a key to select one of 101 (inclusive range 0..100 has 101 different values) 32-bit images to display. You only need 1014 bytes or 404 bytes of ROM/flash, too, less than half that in the first case.




    If your microcontroller's ADC had 16-bit precision mode, or you could use an external serial/SPI 16-bit ADC like ADS8320 (costs a fraction of your DDM4 module), you could use all four significant digits on your LCD. An ADS8320EB costs a couple of euros here, and the typical application circuit shown on the datasheet involves just two filtering capacitors and a 5-ohm resistor, so wiring it up would also be a good exercise.

    Anyway, the 16-bit range, 0 to 65535 inclusive, nicely covers four digits, with over half a bit left over in case the interesting voltage range is smaller than full zero-to-Vcc. (I think it is a pity to only use three digits on a nice pricey four-digit LCD module.)

    Instead of a huge ROM/flash table, I'd only save the ten or so 32-bit words needed for a single digit, the first/leftmost one. Shifting the value eight bits left -- effectively multiplying it by 256 -- moves the image one digit right on the LCD. With a very little effort, you can display any numeric value (of up to four digits) on the LCD.

    Of course, extracting each digit from readout involves a division and modulus by ten (readout % 10extracts the rightmost digit,(readout / 10) % 10the second digit from right,(readout / 100) % 10 the third digit, and(readout / 1000)the leftmost digit, assuming readout has been clamped to range 0 to 9999, inclusive). Division and modulus are slow on most microcontrollers. But, since this is only done when the digits change -- say, a dozen times a second at most --, it does not matter at all.

    I'm not an EE, so I don't know how I'd protect the voltage input from excess voltages or currents (well, maybe zeners to ground via high-power resistors or something), so I wouldn't/couldn't really use this for anything real-worldish. I do have a multimeter for that, though. (No oscilloscope, unfortunately. Those are fun.)

    Questions?
    Last edited by Nominal Animal; 09-02-2014 at 09:08 PM.

  6. #6
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,883
    Once again Nominal Animal, your answer is far too brief [laughs]

    I'm not an EE, so I don't know how I'd protect the voltage input from excess voltages or currents (well, maybe zeners to ground via high-power resistors or something), so I wouldn't/couldn't really use this for anything real-worldish. I do have a multimeter for that, though. (No oscilloscope, unfortunately. Those are fun.)
    Coming from an electronics background, my favourite circuit to protect from overvoltage is a crowbar circuit. Here is a good link Axotron

    You may also want to put a protection diode for reverse inputs as well -> If you put it after the fuse (between the fuse output and ground), you can have the fuse break open on a reverse input.

    However, unless you have a good reason to suspect that there will be a large input, you probably wouldn't spend any extra time/effort/money on a protection circuit: Just accept that if you put too many volts in you will have to make a new circuit.

    I once accidently put 240VAC input a PIC microcontroller (and blew a hole in it) after the circuit that I was dealing with fell off my work bench - Sometimes you just have to start again!
    Fact - Beethoven wrote his first symphony in C

  7. #7
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by Click_here View Post
    Once again Nominal Animal, your answer is far too brief [laughs]
    Sorry, can't seem to help it.

    BTW, the LCD element bit map got garbled (leading whitespace removed); you can see the correct version as plain text. It's supposed to look more like this:
    Code:
    |       05          13          21          29
    |     06  04      14  12      22  20      30  28
    |       07          15          23          31
    |     01  03      09  11      17  19      25  27
    | 00    02    08    10    16    18    24    26
    Quote Originally Posted by Click_here View Post
    However, unless you have a good reason to suspect that there will be a large input, you probably wouldn't spend any extra time/effort/money on a protection circuit: Just accept that if you put too many volts in you will have to make a new circuit.
    You're right. I'd just prefer a more robust circuit, if possible; the display alone likely costs upwards of $25, and if you can protect it with say an optoisolator chip (between the microcontroller and the ADC) and some parts to protect the ADC supply voltage, cost less than $5, it just makes sense to me. (I like my toys a bit more robust than the Chinese variety, you see. I'm not going to mass-produce anything, so every penny of cost is not an issue for me.)

  8. #8
    Registered User
    Join Date
    Sep 2014
    Posts
    6
    "Using the above bit pattern, you create a table of the 256 possible LCD element pictures you wish to show"

    Thank you so much for your detailed answer Nominal Animal!

    I would like create a table as you mentioned. This would represent the ADC reading in a 32 bit format. I can SPI this to the LCD. Unfortunately using a MSP430G2553 micro I can only SPI in chunks of 8 bits. Is there a way to separate $FFFF (from the table) into 8 bit chunks via SPI? Is there something I can read up on for creating a table and to SPI in 8 bit chunks?

    I'm trying to learn C using the MSP430 so the table format would probably be the best starting point.

    Thanks...

  9. #9
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,883
    Sorry, can't seem to help it.
    I personally think that your consistantly detailed answers are one of the assets of this site.

    I'd just prefer a more robust circuit, if possible...
    If this project is something that the OP is doing to learn (and not something for work), it might be a good idea to explore overvoltage circuits. If it's for work, you will need to come up with a business case as to why you would like the device to cost more per unit.

    Here is a good tutorial for the MSP430 http://www.glitovsky.com/Tutorialv0_3.pdf

    I recommend taking time to learn the C language seporate from the MSP430 using Code::Blocks and online tutorials C Tutorial - Learn C - Cprogramming.com

    I also recommend that you look on this forum frequently and try and solve other peoples problems - It teaches you best practices, and it also keeps your skills sharp.
    Fact - Beethoven wrote his first symphony in C

  10. #10
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Good links, Click_here, and thanks for the kind words. Although some like my detailed answers, I do know they annoy others immensely; they do tend to be walls of text. Sorry about that.

    There are also specific tutorials and information on SPI with MSP430G2 microcontrollers here, here, here and here, and lots more.

    Those should not only show totallyclueless and other MSP430G2 microcontroller beginners how others have done similar stuff successfully, but also help understand how stuff works in the microcontroller world in general, and how you can get them to do stuff you yourself want. Ideas maturing and bubbling in your subconscious is always a good thing.

    You'll find information like how to select the proper SPI transfer mode (the polarity of the clock the LCD unit prefers, signal timing), how to set up the SPI transfers, and so on. I'll assume you'll visit those, and won't cover any of it.

    Also, the MSP430G2 USI SPI can transfer "words" of any bit length (up to 16 bits) at a time. For this use case, I do believe 8 bit units work best.

    It also has two separate SPI busses, so using a 16-bit SPI ADC would be even easier than I initially thought with this specific microcontroller; most have only one SPI bus. With MSP430G2, you can put the LCD module and the ADC on separate SPI busses, making configuration and use much simpler. No chip enable I/O lines needed, for example.


    Totallyclueless, if you look at the bit map, you'll notice that each LCD digit, including the decimal point to the left of the digit, is a separate 8-bit byte. Therefore, the main task is to construct the ten digits (0, 1, .., 9) in one byte.

    (In other words, the SPI transfers to the DDM4 LCD module are not just/really 32 bits, it is four groups of eight bits each, first group defining the leftmost digit/element, and the last/fourth group defining the rightmost digit/element. Because of this, it is easier to treat it as four separate elements, rather than one large 32-bit element.)

    Using byte values you can sum together, the parts of each LCD digit are
    Code:
    |       32                          20
    |    64   16                      40  10
    |      128        or, in hex:       80
    |    2     8                      02  08
    | 1     4                     01    04
    Therefore, the byte value describing each decimal digit are
    Code:
    Blank:                                 = 0
    For zero "0": 2 + 4 + 8 + 16 + 32 + 64 = 126
    For one  "1": 8 + 16                   = 24
    For two  "2": 2 + 4 + 16 + 32 + 128    = 182
    and so on. Note that it's much easier to calculate these in hexadecimal, since for example three, "3", is 0x04 + 0x08 + 0x10 + 0x20 + 0x80 = 0xBC = 188.

    In your C code, the array for a single digit is simple:
    Code:
    /* Decimal point is additive to the digit */
    #define DIGIT_DOT 1
    
    static const unsigned char digit[14] = {
        126, /* "0" */
         24, /* "1" */
        182, /* "2" */
        188, /* "3" */
    
        /* digits 4 thorough 9 omitted for brevity */
          
        128, /* digit[10] = "-", minus sign */
          0, /* digit[11] = " ", space (empty) */
        230, /* digit[12] = "E" */
        130, /* digit[13] = "r" */
    };
    Let's assume you have a very nice software calibration setup:
    Code:
    /* Minimum ADC sample, and corresponding displayed value.
    */
    static uint16_t minimum_adc = 0;
    static int16_t  minimum_lcd = 0;   /* -999 to 9999 */
    
    /* Maximum ADC sample, and corresponding displayed value.
    */
    static uint16_t maximum_adc = 255; /* Assuming 8-bit ADC */
    static int16_t  maximum_lcd = 100; /* -999 to 9999 */
    
    /* Note: minimum_adc < maximum_adc, or you'll get garbage out.
     *       If you want inverted output, swap the _lcd values instead!
    */
    Let's write the outlines of the function that computes the four bytes sent to the LCD module -- let's save them in lcd_byte[] array for now --, based on the ADC value.
    Code:
    /** adc_to_lcd() - Scale ADC sample to displayed value range.
    */
    static int16_t adc_to_lcd(uint16_t adc)
    {
        const int16_t  range_lcd = maximum_lcd - minimum_lcd;
    
        /* Clamp adc to minimum..maximum range, inclusive. */
        if (adc < minimum_adc)
            adc = minimum_adc;
        else
        if (adc > maximum_adc)
            adc = maximum_adc;
    
        /* Due to the multiplication, we need 32-bit math.
         * The C compiler can handle this even on 8-bit MCUs,
         * although the computation is relatively slow there
         * (hundreds of cycles). */
        return ( (int32_t)(adc - minimum_adc) * (int32_t)range_lcd
                 + (range_lcd / 2) /* for correct rounding */
               ) / (maximum_adc - minimum_adc)
               + minimum_lcd;
    }
    
    /** lcd_encode_number() - Encode a number -999 to 9999 into LCD bytes.
     * @value:    Between -999 and 9999
     * @decimals: Number of decimals, 0 to 4 (3 if negative).
     *            If zero, no decimal point is shown.
    */
    static unsigned char lcd_byte[4] = { 0U, 0U, 0U, 0U };
    
    static void lcd_encode_number(const int16_t value, const char decimals)
    {
        /* The LCD display module is limited to -999 to 9999
         * (for integersAlthough the above should always produce values only within
         * the minimum_lcd .. maximum_lcd (inclusive) range,
         * the display is limited to -999 to 9999.
         * If we exceed the range, we display "-Err" or " Err".
        */
        if (value_lcd < -999) {
            /* Value is too small. Display "-Err". */
            lcd_byte[0] = digit[10];
            lcd_byte[1] = digit[12];
            lcd_byte[2] = digit[13];
            lcd_byte[3] = digit[13];
        } else
        if (value_lcd < -99) {
            /* We have "-XXX". */
            lcd_byte[0] = digit[10];                        /* digit[10] is '-' */
            lcd_byte[1] = digit[value_lcd / -100];          /* Hundreds */
            lcd_byte[2] = digit[(value_lcd / -10) % 10];    /* Tens */
            lcd_byte[3] = digit[(-value_lcd) % 10];         /* Ones */
            /* Decimal point? */
            if (decimals >= 1 && decimals <= 3)
                lcd_byte[4 - decimals] |= DIGIT_DOT;
        } else
        if (value_lcd < -9) {
            /* We have " -XX". */
            lcd_byte[0] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[1] = digit[10];                        /* digit[10] is '-' */
            lcd_byte[2] = digit[value_lcd / -10];           /* Tens */
            lcd_byte[3] = digit[(-value_lcd) % 10];         /* Ones */
            /* Decimal point? */
            if (decimals >= 1 && decimals <= 2)
                lcd_byte[4 - decimals] |= DIGIT_DOT;
        } else
        if (value_lcd < 0) {
            /* We have "  -X". */
            lcd_byte[0] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[1] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[2] = digit[10];                        /* digit[10] is '-' */
            lcd_byte[3] = digit[-value_lcd];                /* Ones */
            /* Decimal point? */
            if (decimals == 1)
                lcd_byte[3] |= DIGIT_DOT;
        } else
        if (value_lcd < 10) {
            /* We have "   X". */
            lcd_byte[0] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[1] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[2] = digit[11];                        /* digit[11] is '-' */
            lcd_byte[3] = digit[value_lcd];                 /* Ones */
            /* Decimal point? */
            if (decimals == 1)
                lcd_byte[3] |= DIGIT_DOT;
        } else
        if (value_lcd < 100) {
            /* We have "  XX". */
            lcd_byte[0] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[1] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[2] = digit[value_lcd / 10];            /* Tens */
            lcd_byte[3] = digit[value_lcd];                 /* Ones */
            /* Decimal point? */
            if (decimals >= 1 && decimals <= 2)
                lcd_byte[4 - decimals] |= DIGIT_DOT;
        } else
        if (value_lcd < 1000) {
            /* We have " XXX". */
            lcd_byte[0] = digit[11];                        /* digit[11] is ' ' */
            lcd_byte[1] = digit[value_lcd / 100];           /* Hundreds */
            lcd_byte[2] = digit[(value_lcd / 10) % 10];     /* Tens */
            lcd_byte[3] = digit[value_lcd];                 /* Ones */
            /* Decimal point? */
            if (decimals >= 1 && decimals <= 3)
                lcd_byte[4 - decimals] |= DIGIT_DOT;
        } else
        if (value_lcd < 10000) {
            /* We have "XXXX". */
            lcd_byte[0] = digit[value_lcd / 1000];          /* Thousands */
            lcd_byte[1] = digit[value_lcd / 100];           /* Hundreds */
            lcd_byte[2] = digit[(value_lcd / 10) % 10];     /* Tens */
            lcd_byte[3] = digit[value_lcd];                 /* Ones */
            /* Decimal point? */
            if (decimals >= 1 && decimals <= 4)
                lcd_byte[4 - decimals] |= DIGIT_DOT;
        } else {
            /* The value is too large. Show " Err". */
            lcd_byte[0] = digit[11];
            lcd_byte[1] = digit[12];
            lcd_byte[2] = digit[13];
            lcd_byte[3] = digit[13];
        }
    }
    You normally call the above using lcd_encode_number(adc_to_lcd( ADC ), 0) where ADC is the function or expression needed to obtain the next ADC sample.

    It is a good idea to split it into two functions, because that way you now have another function you can reuse later on, one that can encode any number (-999 to 9999, -99.9 to 999.9, -9.99 to 99.99, -.999 to 9.999, and .0 to .9999, inclusive) to the four bytes you send to your LCD module.

    Note that it is very simple to write a lcd_encode_float() function in almost exactly the same way, to encode a floating-point number to the same LCD module. However, users do not like if the decimal point jumps here and there; the decimals approach -- basically a fixed negative power of ten multiplier -- is much more user-friendly, visually. Play with your favourite multimeter, and you'll see why.

    (For example, measure the resistance of some mixed bag of resistors. If the dot would jump, it'd be much easier to misread the display. On the other hand, automatic power-of-ten scale detection would be nice; on mine, I need to twist a knob to get to different scales.)

    I'd also recommend you study the lcd_encode_number() function, until you understand exactly what it does. (The % operator is the modulus operator in C, and yields the remainder after division.)


    There are two approaches to multi-byte (multi-word) SPI transfers:
    • delay-driven, where you wait in a busy-wait loop for the SPI transfer to complete.
      This is very easy to implement, but wastes both CPU power (you do nothing while the SPI transfer is being done), as well as current (you do not normally shift to a low-power state, and keep spinning in high-power state doing nothing).
    • interrupt-driven, where you load each byte to a buffer register, start the transfer, and have an interrupt handler function load the following bytes to the buffer register.
      This is often a bit too steep to learn early in programming, as one must first understand the concepts and the patterns behind this approach. Hard at first, but rewarding.
      The TI SPI examples, I believe, explicitly use the interrupt-driven approach for SPI.

    I don't have an MSP420G2 at hand, so I cannot (do not want to, without hardware to play with) help you with the details on either approach. Even if I had, I'd use GCC and open-source tools in Linux, exclusively. With microcontrollers, it is best if you're tutored by someone with the same tools as you have -- do a web search on MSP420G2 and your development environment keywords to find info best suited for you --, as then you don't stumble on those small, but very annoying differences between the development environments.

    Further questions?

  11. #11
    Registered User
    Join Date
    Jun 2011
    Posts
    4,508
    Quote Originally Posted by Nominal Animal
    ...and if you can protect it with say an optoisolator chip...
    Have you ever looked into digital isolators? I've long since abandoned optical isolators in favor of the digital, due to their smaller size, cheaper cost (for comparable regulatory specs), and more robust performance. With multiple channels per device, they are especially good when multiple signals require electrical isolation.

    A quick search yielded this white paper comparing the two technologies.

    I use the ADuM240x parts from Analog Devices in my designs. They have easily survived UL EMC testing in various user interface designs I've done.

  12. #12
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by Matticus View Post
    Have you ever looked into digital isolators?
    I thought they were (inherently) not as robust as optical isolators. I'm glad to see I was wrong; they do open up new options for me I hadn't thought of before!

    The only downside I see with ADuMs is they're SOIC packages, and soldering them with hobbyist tools is a bit trickier than through-hole parts. It's not that hard, there are very good tutorials on youtube, you just need to practice a bit, I think. DIP packages like 4N25 and so on are cheap and easy to work with -- good for starter/hobbyist stuff, where having basic protection, and understanding the principles and reasons, is the main thing in my opinion.

    Oh, and fun. Fun is really important.

    I personally have more fun, if forgetting to not wear woolly socks or to properly ground myself every few seconds or so, does not fry up my microcontroller.

    (I've zapped a 5 cm / two-inch static electricity arc on a dry winter day to a door handle. My finger was numb from tip to wrist for hours, it seemed. Much worse than any of the 240VAC mains zaps I've managed to give myself. )

    Quote Originally Posted by Matticus View Post
    I've long since abandoned optical isolators in favor of the digital. [ ... ] The ADuM240x parts from Analog Devices [ ... ] have easily survived UL EMC testing in various user interface designs I've done.
    Those are nice! I've used something as silly as connect two microcontrollers via SPI using three TOSLINK links, both out of interest and to make sure the two are truly isolated from each other.

    My most ambitious idea is to create a 4-stepper controller board, similar to SmoothieBoard, using Allegro A4983 chips, with a Cortex M4-based ARM microcontroller (similar to Teensy 3.1, which I do like a lot) -- but have the motor side isolated, in particular the motor ground totally separate from the digital ground. Have the A4983 chips lined up on the edge of the board, leads parallel to the edge, no caps or resistors in the way, so I can use thermal pads on both top and bottom sides to sandwich them in a standard U aluminium profile in thermal connection to the enclosure; also works to keep that side of the board in place. They don't generate that much heat, but that would allow max motor currents, and also keep the board in place. On other side, use clips to hold the entire board in place, so no need to drill holes through the enclosure. Use something like a Hammond 1590X aluminium enclosure, or smaller, for the entire thing: real rugged and robust operation, with native USB connection (and very little risk of damaging your computer through ground loop or motor voltage spike), without costing more than a typical Arduino. Fully programmable via the USB cable, no drivers, no FTDI serial-to-USB bridge to limit your USB options -- and easy to program using only open source tools (arm-gcc et al). Some Cortex-M4 chips even have Ethernet MAC and PHY built-in, so all you need is a MagJack to get Ethernet support.

    I mention it in this thread, because all of the requirements needed to implement that are clearly listed on the datasheets and manufacturer tech notes, including example application circuits, so it's not outside the capability of a well-motivated, inquisitive hobbyist. Sure, an experienced EE can definitely do it better, and avoid some of the more complicated/sneaky problems regarding signal quality and trace lengths and whatnot, probably design it in a fraction of the time it'd take me, and only need a couple of board revisions to get it right (good enough to satisfy a stickler like me, that is). Board manufacturing, even in singles, is quite cheap nowadays, so you don't even need to etch the boards yourself.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. scaling function
    By rozner in forum Game Programming
    Replies: 1
    Last Post: 10-23-2006, 12:55 AM
  2. Ever heard of a Grapple? (No, not for scaling buildings.)
    By LuckY in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 01-24-2006, 03:53 PM
  3. Direct3D translating and scaling
    By bennyandthejets in forum Game Programming
    Replies: 2
    Last Post: 12-24-2004, 12:51 AM
  4. image scaling
    By DavidP in forum Game Programming
    Replies: 1
    Last Post: 06-23-2004, 10:48 AM
  5. Scaling Progress Steps :: MFC
    By kuphryn in forum Windows Programming
    Replies: 0
    Last Post: 11-21-2002, 03:30 PM