Showing posts with label PIC16. Show all posts
Showing posts with label PIC16. Show all posts

Sunday, March 27, 2016

Hacking Honda Odyssey 2007 RES DVD-player: part 2

Part 1: Overview
Part 2: Hardware (This part)

Hardware


I finally built a PCB that works great and  even helped me to track down a nasty bug (took me a while, too. Hang on here with me, I'm actually going to tell you about it because it's fun).
But now, hardware.




Saturday, March 5, 2016

Hacking Honda Odyssey 2007 RES DVD-player: part 1

Part 1: Overview (this part)
Part 2: Hardware

Infotainment/NAVI system in Honda Odyssey 2007 is a huge monster – it has a luxury audio unit with 6 CD changer, a DVD-player, large NAVI screen in the dashboard, dashboard and steering wheel controls, rear screen with controls, IR remote and IR headphones. Awesome, isn't it?

Well, the problem is that we live in 2016 and it really does suck when you are stuck with the only choice between CDs and DVDs. If you want MP3, computer video, USB input, Bluetooth or anything else – your only option is the AUX input (composite video + stereo audio). It's definitely something, but if you are a maker, you can't be really satisfied with it, can you?

So I thought – why don't I look into how the hell this DVD works and if it would be possible to replace it with something more interesting and flexible – think a Raspberry PI or alike.


Tuesday, January 8, 2013

Can't find 0x210 words (0x210 withtotal) for psect "swtext1" in segment "CONST"

Have you ever seen something like this:

Error [1347] ; 0. can't find 0x210 words (0x210 withtotal) for psect "swtext1" in segment "CONST" (largest unused contiguous range 0x100)

Well, I crashed my head over the table the whole morning playing with buffers sizes, defines, deleting functions etc... The linker kept giving me the above error. Then I searched and fount this thread. One cool thing about this thread is that it contains a pretty cool step-by-step on how to trace to the root of the problem:

Saturday, August 25, 2012

How to measure RPM in a glimpse of an eye

So, yes. I just assembled a setup to measure rotation speed of an RC model motor. It uses a reflective IR sensor to provide high level signal to MCU whenever a blade of a propeller comes by in front of it. OK, we've got a series of impulses with the frequency of motor revolutions divided by number of blades, but how do we know how many rpm does it make?

1. Measuring frequency


This was my very first take on the problem. I decided I could take a time interval, a second for simplicity, and just count how many times blades made the sensor go off. Divide than by number of blades and multiply by 60 (seconds in a minute) to get your rpm. Once you do that, you will immediately notice, that the result comes in multiples of 60s. If you had 10 rps (revolutions per second), you calculate for 600 rpm, 11 rps account for 660 rpm. This is good +=5% error, and it's called discretization error. Surely the higher the speed, the lower this error is, but it's still very annoying. Another error comes from instability of revolution period. This also create a lot of trouble if the rotation speed is low.

More here, if you really take 1 second interval, the whole system does not respond very well - you may want to have refresh rate at least 3 times per second... And the shorter the measurement interval is, the bigger is discritization (if you have 330ms, the result will come now in multiples of 180!) error and the higher is the minimum rotation speed you can measure (for minimum of 3rps - for wich you'll have yet to fight, I'd say it's rather 6 rps with 330ms period - you'll have 180 rpms) - which is not a very huge problem, but still lousy.

There must be another method, I thought, that allows e.g. www.HobbyKing.com to create Turnigy Multi-Blade Micro Tachometer and claim minimum rpm of 10 rpm as well as high precision of measurement. And there's one. Thinking of it now, I believe it's a trivial and obvious solution. However I had to read a book on measurements to get to this.

2. Measuring period


That's it and that's really easy. Instead of counting how many blades will pass sensor in time period, you rather count how many time periods pass in between two blades crossing sensor FOV. I initially set up MCU to count 1us intervals, but found out my 16 bit counter overflows too fast and I can't measure low rpm. So I just used prescaler.

It's quite easy to reverse-calculate all the parameters here. Imagine you need to go as low as 10rpm as Turnigy tachometer does. So you need to setup MCU so 16 bit counter overflows in longer than 6s (10 rpm is 0,167rps or 1/0,167 = 6 seconds per revolution). That is 6/65536 = ~92us per timer clock.
Now, what is the highest speed you can measure? With e.g. 1% precision you may want to have at least 100 timer clocks per revolution, i.e. 9,20 ms. That is 108 rps or 6522 rpm.

And that calculation is for 1 blade propeller (that are not often met in the wild). If there are two blades the calculation above will be for 5rpm min and 3260 rpm max.

What's the estimated error? Absolute maximum error for this method is not higher than 1 timer clock (92us). For 10rpm error is 92us/6s. Which is tiiiiinyyyy. Not noticeable. Means not relevant. For 6522 rpm it's 92us/9.2ms = 1%

Now you can almoset instantly measure rpms with high enough accuracy. Oh, you might think 6522 rpm (3260rpm for a two-blade propeller) is nonsense? Tiiiiinyyyy? Not noticeable? Means not relevant? Well, tell me how to handle higher rpm in comments.

Happy measuring!
Cheers!

P.S. Oh, nearly forgot. Here's some code for PIC:

#include "htc.h"
#include "freq_meter.h"
#include "hw_configuration.h"
#include <stdio.h>
#include "lcd.h"

__CONFIG(FOSC_INTOSC & CLKOUTEN_OFF & WDTE_OFF & PWRTE_ON & PLLEN_ON);

#define TMR0_LCD_REFRESH_RATE 5
unsigned char outputBufferStr1[9];
unsigned char outputBufferStr2[9];
unsigned char outputBuffer[40];
unsigned int TMR0_OverflowCounter = TMR0_LCD_REFRESH_RATE;
bit outputResultFlag = 0;
bit peakHoldFlag;
bit errorFlag = 0;
unsigned int cntval = 0;
unsigned int maxcntval = 0;
unsigned long rpm = 0;
unsigned long maxRpm = 0;

void main (void)
{
    picSetup();
    LCD_Init ();

    TMR1H = 0;
    TMR1L = 0;

    peakHoldFlag = 1;

    LCD_WriteStr2 ("Hi!");
    while(1)
    {   
        if (outputResultFlag)
        {
            //LCD_ClearAndHome();
            if (errorFlag)
            {
                RB3 = 1;
                LCD_WriteStr1 ("  Error!");
            } else
            {
                RB3 = 0;
                rpm = 15000000/cntval;
                if (rpm > maxRpm) maxRpm = rpm;
                sprintf(outputBufferStr1, "%5urpm", (unsigned int)rpm);
                LCD_WriteStr1 (outputBufferStr1);
            }
            if (peakHoldFlag)
            {
                sprintf(outputBufferStr2, " pk%5u", (unsigned int)maxRpm);
                LCD_WriteStr2 (outputBufferStr2);
            }
            outputResultFlag = 0;
        }
    }
}

void interrupt isr (void)
{
    if (TMR1IE && TMR1IF)
    {
        TMR1IF = 0;       
        errorFlag = 1;
    }

    if (CCP1IE && CCP1IF)
    {
        CCP1IF = 0;
        if (errorFlag)
        {           
            TMR1L = 0;
            TMR1H = 0;
            cntval = 0;
        }
        else
        {
            cntval = (CCPR1H << 8) + CCPR1L;
            TMR1L -= CCPR1L;
            TMR1H -= CCPR1H;
        }
        errorFlag = 0;
    }

    if (TMR0IF)
    {
        TMR0IF = 0;
        if (TMR0_OverflowCounter-- == 0)
        {
            outputResultFlag = 1;
            TMR0_OverflowCounter = TMR0_LCD_REFRESH_RATE;
        }
    }
    
}


Sunday, May 13, 2012

How to implement hardware-only SIR (Slow IrDA) on a Microchip PIC16 MCU using Data Signal Modulator (DSM)

In one of my projects (actually, in HDD POV clock v.2) I had to transfer data wirelessly over a distance about 7cm (~3"). After some research I was pointed to IrDA protocol and I was told this is the best option and I shouldn't be inventing a bicycle. Indeed if I had an IrDA transceiver, I would be totally OK. But I didn't and I couldn't find any available within easy reach. reasonable time and for a reasonable price. Those things are pretty obsolete by now you know.
While searching I also figured out that STM8 MCUs have SIR built into UART, but I had to stick to PIC16F1827... So, what do I do?