Ok, lets check the basics.
During PIC programming:
1. If you are seeing all four digits light up it means the processor clock must be running but do you have the configuration fuse set to XT or HS?
2. Do you have the watchdog timer enabled? It should NOT be enabled for your program to work.
3. Do you have Low Voltage Programming (LVP) disabled? It should be disabled.
Hardware:
1. Do you have the 0.1uF capacitor wired across VSS and VDD pins AS CLOSE AS POSSIBLE TO THE PIC.
2. Are the crystal and the two crystal loading capacitors connected with short wires?
I'm not sure you need the extra diode in the IR receiver. You can test if the IR is working quite easily, connect a headphone/earphone in series with a 1K resistor across the 10K resistor in the collector of the BC557. Listen while you send some data from a TV/VCR remote control. If the receiver is working you should hear a buzz as the keys are pressed. If the buzz is there, your problem is in the IR transmitter stage.
Personally, I would increase the value of the 1.8K resistor to 47K or more, it's only there to prevent any leakage through the IR receiver biasing the transistor on when no light is present.
Brian.
Good, the electronics part seems to work. I think the software needs looking at though. You may have to live with the fact that multiplexing the display and measuring RPM are mutually exclusive. You may only be able to do one or the other, especially when you have delay routines to slow the display multiplexing, at best you will get some flickering as the multiplexing is disrupted. Can you show the full code so I can see what method for counting the pulses you are using please. Also give me some idea of how many pulses per second you are expecting and the maximum number it could ever reach.
I'm thinking a better solution would be to use two or even all three timers. One to open and close the period measuring window, one to count the pulses and maybe one to keep the multiplexing at a constant rate to reduce flickering. Incidentally, at the moment, your code only looks to be able to count 255 pulses per second, if you are using a toothed (cogs) wheel as the IR beam disrupter it means you could only measure slow speeds.
Brian.
I'll try, are you using the Mikroe C compiler that the original project used?
I use a different compiler but I do have a copy of the Mikroe C trial version. I'll investigate tomorrow (it's late at night here) and see if I can help. There is no way I can build any hardware at the moment though so you will have to do final debugging yourself.
Brian.
void NextLED();
void CalculateRPM();
//-------------- Array of segment values for common cathode 7-seg. display
const unsigned short segments[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
sbit IR_Tx at RB7_bit;
sbit IR_Rx at RA4_bit;
unsigned short Digit[4], ActiveDigit = 0, LastRxState = 0;
unsigned int PulseCount;
void main()
{
TRISB = 0b00000000; // Set PORTB direction to be output
TRISA = 0b00110000; // Set PORTA direction to be output
PORTB = 0x00; // Turn OFF LEDs on PORTB
CMCON = 7; // Disable comparators
OPTION_REG = 0b10000110; // TOCS=0 for internal clock Counter mode, PSA=0 for TMR0 prescaled 1:128
T1CON = 0b00110001; // Timer 1 counts internal clocks prescaled 1:8
INTCON = 0b01100000; // Enable TMR0 and PIE interrupts
PIE1 = 0b00000001; // Enable TMR1 interrupts
INTCON |= (1<<GIE); // Enable global interrupts
IR_Tx = 1; // Turn ON IR emitter
// count rising edge transitions
while(1)
{
if((IR_Rx == 1) && (LastRxState == 0)) PulseCount++;
LastRxState = IR_Rx;
}
}
// TMR0 times how long each Digit is displayed, TMR1 times how long pulses are counted for
void interrupt()
{
if(INTCON.TMR0IF)
{
TMR0 = 0x53; // should be ~5mS at 4.433MHz clock
NextLED();
INTCON.TMR0IF = 0;
}
else if (PIR1.TMR1IF)
{
TMR1H = 0x27; TMR1L = 0x8C; // should be ~100mS at 4.433MHz clock
CalculateRPM();
PulseCount = 0;
PIR1.TMR1IF = 0;
}
}
void CalculateRPM()
{
Digit[0] = (short)PulseCount%10;
Digit[1] = (short)(PulseCount/10);
Digit[2] = (short)(PulseCount/100);
Digit[3]= (short)(PulseCount/1000);
}
void NextLED()
{
PORTA &= 0xF0; // turn all LED drives off
if(ActiveDigit > 3) ActiveDigit = 0;
PORTB = segments[Digit[ActiveDigit]];
PORTA |= (1 << ActiveDigit);
ActiveDigit++;
}
That's strange. The IR LED is turned on and left on. Your code turned it on and off as it measured pulses but mine should stay on all the time. Try simply connecting the IR LED across the supply through it's series resistor and check it stays lit up.
The fact that your remote control made the reading change is good, it shows that the counting routine is working. The remote will send pulses in brief bursts, it wont be continuous so don't expect a steady display.
Each digit on the display should light for about 4mS and they should light in sequence 1,2,3,4,1,2,3,4... At 4mS you shouldn't see much flickering but you can adjust the multiplexing speed by changing the value loaded into TMR0. A higher value will make the multiplex time shorter (faster scan). Check nothing else is wrong first though because it is already quite fast.
The compiler I normally use is 'WizC Pro' but I also use XC8/XC16 and often code in assembly language. WizC has a few 'quirks' but it has by far the best and fastest simulator I've ever used.
Brian.
That's strange. The IR LED is turned on and left on. Your code turned it on and off as it measured pulses but mine should stay on all the time. Try simply connecting the IR LED across the supply through it's series resistor and check it stays lit up.
The fact that your remote control made the reading change is good, it shows that the counting routine is working. The remote will send pulses in brief bursts, it wont be continuous so don't expect a steady display.
Each digit on the display should light for about 4mS and they should light in sequence 1,2,3,4,1,2,3,4... At 4mS you shouldn't see much flickering but you can adjust the multiplexing speed by changing the value loaded into TMR0. A higher value will make the multiplex time shorter (faster scan). Check nothing else is wrong first though because it is already quite fast.
The compiler I normally use is 'WizC Pro' but I also use XC8/XC16 and often code in assembly language. WizC has a few 'quirks' but it has by far the best and fastest simulator I've ever used.
Brian.
void CalculateRPM()
{
Digit[0] = 4;
Digit[1] = 3;
Digit[2] = 2;
Digit[3] = 1;
}
It's no wonder the IR made it go blank, you would be passing around 100mA through it! I suggest you change the 68 Ohm resistor to 390 Ohms (~20mA) before the LED burns out.
I have to add that it sounds like you are pushing the battery to the limit anyway, you really should be using a regulated mains power supply, if you are using one of those small batteries with two clips at one end, it will struggle to provide sufficient voltage, the way it fails under only 100mA extra load confirms this.
Unfortunately, the simulation in Mikroe C doesn't show the timers counting so no interrupts are triggered. I'm not sure why but it prevents me seeing the multiplexing so I can't check if the correct digits are being shown.
Please try changing these lines:
and run it to see if it displays '1234'. What I'm trying to establish is whether the displaying routine is at fault or there is a calculation problem. Putting known values in the program should narrow it down.Code:void CalculateRPM() { Digit[0] = 4; Digit[1] = 3; Digit[2] = 2; Digit[3] = 1; }
If it does display '1234' the problem is almost certainly due to the calculation mixing 8-bit and 16-bit values, that's why I added the (short) cast to the variables but it may not be working as expected.
Brian.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?