Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Microchip PIC program problem

Status
Not open for further replies.

alpha91

Full Member level 3
Full Member level 3
Joined
Sep 23, 2011
Messages
168
Helped
1
Reputation
2
Reaction score
2
Trophy points
1,298
Activity points
2,625
Hi all, I am doing a mini project which is trying to make a electronic roulette with 16 output (LED) with PIC 16F628a
may I know how to set the delay time as a constant like make it as an integer?

i tried to make it like this
delay_ms (i);
but it end up become error.
 
Last edited:

...may I know how to set the delay time as a constant like make it as an integer?
i tried to make it like this
delay_ms (i);
but it end up become error.
Simple (not really accurate but working) mikroC solutions:
Code:
void DelayV_ms(unsigned ms) {
  if (ms) {
    do {
        Delay_us(988);  // experimental value
    } while (--ms);
  }
}

// OR (and if 255 ms is also enough as max delay):

void DelayV_ms(char ms) {
  while (ms) {
      Delay_us(988);
      --ms;
  };
}

// OR use the VDelay_ms(unsigned ms) library function (much larger code !)
 
If using HiTech-C, the delay macros have 2 under-scores in front of the function. You'll also need to have the clock speed defined (_XTAL_FREQ) so the macro can calculate the delay. Now that I look at your request, this probably won't work using a variable (i in your case).

Code:
#define _XTAL_FREQ		18432000				// 18.432 MHz Osc.

__delay_ms(100);
 
Hi,

What error?

Klaus


...and which compiler?

Please show your code.

Brian.





Dear all, sorry for my missout.
I am using MikroC compiler. I got an error mentioned that the i should be integer greater than 0 .
Actually what i want is to change the delay time from short to longer as i want to make it like roulette which the light moving from fast and then slow down and stop.


My code is shown as below.

Code:
#define _XTAL_FREQ 4000000
signed int i= 0;
void main() {
 i = 500;
TRISA = 0x00100000;
TRISB = 0X00;
CMCON = 0x07; // To turn off comparators
PORTB = 0x01;
  do // To set infinite loop
  {
 Delay_ms(300); // 300 mili seconds delay
    PORTB = PORTB<<1; //Shifting right by one bit
    if(PORTB >= 0b10000000) //To reset to 00000001
    {                          //when the count becomes 10000000
       Delay_ms(i); // 350 mili seconds delay
       PORTB = 1;
    }
  }while(1); // To set infinite loop}while(1); // To set infinite loop

}


Simple (not really accurate but working) mikroC solutions:
Code:
void DelayV_ms(unsigned ms) {
  if (ms) {
    do {
        Delay_us(988);  // experimental value
    } while (--ms);
  }
}

// OR (and if 255 ms is also enough as max delay):

void DelayV_ms(char ms) {
  while (ms) {
      Delay_us(988);
      --ms;
  };
}

// OR use the VDelay_ms(unsigned ms) library function (much larger code !)


I see. thanks for your helped. I will try this out.


If using HiTech-C, the delay macros have 2 under-scores in front of the function. You'll also need to have the clock speed defined (_XTAL_FREQ) so the macro can calculate the delay. Now that I look at your request, this probably won't work using a variable (i in your case).

Code:
#define _XTAL_FREQ		18432000				// 18.432 MHz Osc.

__delay_ms(100);

Hi, actually i need to make the delay time to be variable so that i am able to decrease it from time to time.
 

hello,


you can use VDelay from MikroC or build you own ...
delay between each step can be linear or logaritmic

Code:
#define _XTAL_FREQ 4000000
unsigned int i= 0;   // 0 to 65535


void Variable_Delay_mS(unsigned int T)
{
 unsigned int t1;
 t1=T;
  While(t1>0)
  {
  Delay_ms(1);
  t1--;
  }
 }

void main() {
 i = 512; // starting value 
TRISA = 0x00100000;
TRISB = 0X00;
CMCON = 0x07; // To turn off comparators
PORTB = 0x01;
  do // To set infinite loop
  {
    PORTB = PORTB<<1; //Shifting[B]  LEFT[/B] !  by one bit
    if(PORTB >= 0b10000000) //To reset to 00000001
    {                          //when the count becomes 10000000
        PORTB = 1;
        i=512;
     }
     Variable_Delay_ms(i); // 500 mili seconds delay
     i=i>>1;  // divide by 2 => log step
     // or i=i-32 ;   // => linear step 
  }while(1); // To set infinite loop}while(1); // To set infinite loop

}
 

hello,


you can use VDelay from MikroC or build you own ...
delay between each step can be linear or logaritmic

Code:
#define _XTAL_FREQ 4000000
unsigned int i= 0;   // 0 to 65535


void Variable_Delay_mS(unsigned int T)
{
 unsigned int t1;
 t1=T;
  While(t1>0)
  {
  Delay_ms(1);
  t1--;
  }
 }

void main() {
 i = 512; // starting value 
TRISA = 0x00100000;
TRISB = 0X00;
CMCON = 0x07; // To turn off comparators
PORTB = 0x01;
  do // To set infinite loop
  {
    PORTB = PORTB<<1; //Shifting[B]  LEFT[/B] !  by one bit
    if(PORTB >= 0b10000000) //To reset to 00000001
    {                          //when the count becomes 10000000
        PORTB = 1;
        i=512;
     }
     Variable_Delay_ms(i); // 500 mili seconds delay
     i=i>>1;  // divide by 2 => log step
     // or i=i-32 ;   // => linear step 
  }while(1); // To set infinite loop}while(1); // To set infinite loop

}

Hi, first of all, thank you very much for your help. I will try this later. I had done it manually by duplicating the code to few step.
my code is as below

Code:
#define _XTAL_FREQ 4000000
void main() {
unsigned int i = 0;
int result;
TRISA = 0x00100000;
TRISB = 0X00;
CMCON = 0x07; // To turn off comparators
PORTA = 0x00;
PORTB = 0x01;
  do // To set infinite loop
  {
        start:
        // fast running
         for(i = 0; i<20; i++){
         delay_ms(100);
         PORTB = PORTB<<1; //Shifting right by one bit
         if(PORTB >= 0b10000000) //To reset to 00000001
         {                          //when the count becomes 10000000
         PORTB = 1;
         }
         }
         // medium speed running
         for(i=20; i<30; i++){
         delay_ms(200);
         PORTB = PORTB<<1;
         if(PORTB >= 0b10000000) //To reset to 00000001
         {                          //when the count becomes 10000000
         PORTB = 1;
         }
         }
         // slow running
         for(i=30; i<35; i++){
         delay_ms(300);
         PORTB = PORTB<<1;
         if(PORTB >= 0b10000000) //To reset to 00000001
         {                          //when the count becomes 10000000
         PORTB = 1;
         }
         }
         // slowest speed
         for(i=45; i<48; i++){
         delay_ms(450);
         PORTB = PORTB<<1;
         PORTB = 0x00;
         goto RANDOMLIGHT;
         }
         
         RANDOMLIGHT:{
         result = rand();      // generate random value from 0 to 32767
         result = result/1000;
         switch (result){
         case 0:PORTB = 0x01;
         delay_ms(3000);
         i== 1;
         goto start; // restart
         case 1:PORTB = 0x02;
         delay_ms(3000);
         i== 1;
         goto start; // restart
         case 2:PORTB = 0x04;
         delay_ms(3000);
         i== 1;
         goto start;  // restart
         case 3:PORTB = 0x08;
         delay_ms(3000);
         i== 1;
         goto start; // restart
         case 4:PORTB = 0x10;
         delay_ms(3000);
         i== 1;
         goto start; // restart
         case 5:PORTB = 0x20;
         delay_ms(3000);
         i== 1;
         goto start; // restart
         case 6:PORTB = 0x40;
         delay_ms(3000);
         i== 1;
         goto start;  // restart
         case 7:PORTB = 0x80;
         delay_ms(3000);
         i== 1;
         goto start;  // restart
         case 8:PORTB = 0x08;
         delay_ms(3000);
         i== 1;
         goto start;  // restart
         case 9:PORTB = 0x04;
         delay_ms(3000);
         i== 1;
         goto start;  // restart
         }
         }
  
  }while(1); // To set infinite loop}while(1); // To set infinite loop

}

Now, there are few problems arise.
1. the LED that light up use to constant between few instead of really random between all 8 LEDs.
2. there is a very long delay after the LED running stop and the LED lights up. is it because of the random instruction require a lot of scan time?
3. the LED does not delay for 3 second when it is light up (at the CASE statement part).
 

Ugh!

Please remove every instance of 'goto' and add 'break' to the end of each 'case' comparison. Also remove the 'goto RANDOMLIGHT' and replace it with 'RANDOMLIGHT()' and turn ther RANDOMLIGHT code into a function.

Why not use a simple array to hold the PORTB values and remove the switch() altogether?

What are all the lines 'i== 1;' supposed to do?

To be honest, it needs restructuring and rewriting, it can be done in half the lines and be much easier to follow.

Brian.
 
Why in the digital roulette wheel spinning is required ? Why not just display the final random led position instantly ?
 
I have to admit that I'm not totally aware of the implications of the following construct, whether if falls on the "read-modify-write" category for an access to the register of an I/O or not, but I would be carefull on using this :

Code:
PORTB = PORTB<<1

Consider using variables, just updating the result to the port after calculating.
 
Why in the digital roulette wheel spinning is required ? Why not just display the final random led position instantly ?

Why do the "drums" on slot machines spin when the outcome of the pull is predetermined? Aesthetics. Suspense.
 
I think the original problem and error is due to the fact that the delay 'function' the OP used may not actually be a "function" but a "macro" which didn't like the use of a variable. I've seen this sort of thing before where the preprocessor expects to be able to calculate the value to be used for the delay to a single number and cannot handle using a variable in that calculation.
Just a guess...
Susan
 

I think the original problem and error is due to the fact that the delay 'function' the OP used may not actually be a "function" but a "macro" which didn't like the use of a variable. I've seen this sort of thing before where the preprocessor expects to be able to calculate the value to be used for the delay to a single number and cannot handle using a variable in that calculation.
Just a guess...
Susan

Why do the "drums" on slot machines spin when the outcome of the pull is predetermined? Aesthetics. Suspense.

I have to admit that I'm not totally aware of the implications of the following construct, whether if falls on the "read-modify-write" category for an access to the register of an I/O or not, but I would be carefull on using this :

Code:
PORTB = PORTB<<1

Consider using variables, just updating the result to the port after calculating.

Why in the digital roulette wheel spinning is required ? Why not just display the final random led position instantly ?

Ugh!

Please remove every instance of 'goto' and add 'break' to the end of each 'case' comparison. Also remove the 'goto RANDOMLIGHT' and replace it with 'RANDOMLIGHT()' and turn ther RANDOMLIGHT code into a function.

Why not use a simple array to hold the PORTB values and remove the switch() altogether?

What are all the lines 'i== 1;' supposed to do?

To be honest, it needs restructuring and rewriting, it can be done in half the lines and be much easier to follow.

Brian.

I had edited my code as follow:

Code:
#define _XTAL_FREQ 4000000
unsigned int i = 0;
void RANDOM_LIGHT() {
  int result;
         result = rand();      // generate random value from 0 to 32767
         result = result/1000;
         switch (result){
         case 0:
         PORTB = 0x01;
         delay_ms(3000);
         i== 1; // restart
         // case 1
            case 1:
            PORTB = 0x02;
            delay_ms(3000);
            i== 1;
            // restart
            break;
         // case 2
            case 2:
            PORTB = 0x04;
            delay_ms(3000);
            i== 1;
            // restart
            break;
         // case 3
            case 3:
            PORTB = 0x08;
            delay_ms(3000);
            i== 1;
            // restart
            break;
         // case 4
            case 4:
            PORTB = 0x10;
            delay_ms(3000);
            i== 1;
            // restart
            break;
         // case 5
            case 5:
            PORTB = 0x20;
            delay_ms(3000);
            i== 1;
            // restart
            break;
         //case 6
            case 6:
            PORTB = 0x40;
            delay_ms(3000);
            i== 1;
            // restart
            break;
         // case 7
            case 7:
            PORTB = 0x80;
            delay_ms(3000);
            i== 1;
            break;
         // case 8
            case 8:
            PORTB = 0x08;
            delay_ms(3000);
            i== 1;
            break;
         // case 9
            case 9:
            PORTB = 0x04;
            delay_ms(3000);
            i== 1;
            break;
         }
         }

void main() {


TRISA = 0x00100000;
TRISB = 0X00;
CMCON = 0x07; // To turn off comparators
PORTA = 0x00;
PORTB = 0x01;
  do // To set infinite loop
  {
        start:
        // fast running
         for(i = 0; i<20; i++){
         delay_ms(100);
         PORTB = PORTB<<1; //Shifting right by one bit
         if(PORTB >= 0b10000000) //To reset to 00000001
         {                          //when the count becomes 10000000
         PORTB = 1;
         }
         }
         // medium speed running
         for(i=20; i<30; i++){
         delay_ms(200);
         PORTB = PORTB<<1;
         if(PORTB >= 0b10000000) //To reset to 00000001
         {                          //when the count becomes 10000000
         PORTB = 1;
         }
         }
         // slow running
         for(i=30; i<35; i++){
         delay_ms(300);
         PORTB = PORTB<<1;
         if(PORTB >= 0b10000000) //To reset to 00000001
         {                          //when the count becomes 10000000
         PORTB = 1;
         }
         }
         // slowest speed
         for(i=45; i<48; i++){
         delay_ms(450);
         PORTB = PORTB<<1;
         PORTB = 0x00;
         RANDOM_LIGHT();
         }
         

  
  }while(1); // To set infinite loop}while(1); // To set infinite loop

}


i == 1 function is to reset the "i" so that when a full cycle is finish, the LED will run like a roulette wheel again.
(i am using value "i" to set the LED run in different speed as you can see in void main function)

but my function still cant perform like what i want. Does anyone know which part is having problem?:bang:
 

No seed for the rand() function ?

Anyway, this is too vague:
my function still cant perform like what i want. Does anyone know which part is having problem?
 

"i == 1" does not set the value to 1.

change it to "i = 1" !

Do you realize you can remove all those "delay_ms(3000)" lines and replace then with a single one at the end of the switch() section.

Brian.
 

i == 1 function is to reset the "i" so that when a full cycle is finish, the LED will run like a roulette wheel again.
(i am using value "i" to set the LED run in different speed as you can see in void main function)
This is a fairly common mistake - confusing the assignment operator ('=') with the equality boolean comparison operator ('==') although it is usually confused the other way around (making an assignment in an 'if' statement rather than a useless comparison when an assignment is intended).
To do what you state (reset the variable 'i' to 1) use
Code:
i = 1;
Having said that, in each of the 'case' statements, you have a 3 second delay and an assignment of i to 1. You can save a whole lot of code by refactoring these statements out of each 'case' statement and put them once at the end, after the 'switch' block.
Be careful with the way you generate the random value in the 'result' variable. First you generate (according to your comment a value form 0 to 32767. You then divide this by 1000 which makes the value from 0 to 32. When you use the value in the 'switch' statement, you only provide case clauses for the values form 0 to 9. That means the values from 10 to 32 will be ignored. If that is what you intend to do then fine but it looks a bit "odd" - did you mean to generate a random number from between 0 and 9 or did you mean to ignore about 2/3rds of the generated values? A comment or a 'default' clause might help here.
but my function still cant perform like what i want. Does anyone know which part is having problem?
The part 'having [a] problem' is that you have not described the problem! What is it doing that you do not want it to do? What is is NOT doing that you intend.
There may be a logic error in your main loop. As you go through each of the 'for' loops, you set the value of PORTB so that it (presumably) turns on a LED in a sequence. Note that the last 'for' loop has 2 consecutive assignments to PORTB which will not show you anything on the LEDs.
Also in the last 'for' loop yo call the 'RANDOM_LIGHT' function which will set a random pattern on the LEDs but for only 450 mSec.
The end effect will be the LEDs going through a (presumably slowing) sequence pattern and then 3 random flashes within about a second and then back to the sequence pattern.
Is this really what you are after?
Susan
 

"i == 1" does not set the value to 1.

change it to "i = 1" !

Do you realize you can remove all those "delay_ms(3000)" lines and replace then with a single one at the end of the switch() section.

Brian.

Not just the delay_ms(3000) the i = 1 line could also reside after the switch() section.

Not being a software engineer, but I'm wondering wouldn't the switch be better off as an array of PORTB values that you just index through assigning to PORTB with a for loop? Would sure use a lot less repetitive code.
 

Hello guys


Has any one realized of this?

#define _XTAL_FREQ 4000000
unsigned int i= 0; // 0 to 65535


void Variable_Delay_mS(unsigned int T)
{
unsigned int t1;
t1=T;
While(t1>0)
{
Delay_ms(1);
t1--;
}
}

void main() {
i = 512; // starting value
TRISA =0x00100000; //THIS LINE!!
TRISB = 0X00;
CMCON = 0x07; // To turn off comparators
PORTB = 0x01;
do // To set infinite loop
{
PORTB = PORTB<<1; //Shifting LEFT ! by one bit
if(PORTB >= 0b10000000) //To reset to 00000001
{ //when the count becomes 10000000
PORTB = 1;
i=512;
}
Variable_Delay_ms(i); // 500 mili seconds delay
i=i>>1; // divide by 2 => log step
// or i=i-32 ; // => linear step
}while(1); // To set infinite loop}while(1); // To set infinite loop

}

The port state (I/O) is being settled to 0x100000 (100000h), equal to 1048576 in decimal and 0b100000000000000000000, which I think it's overflowing the register just a little bit... You cannot put a million liters of water in a 256L barrel, it's not going to work.

He must had wanted to write TRISA =0b00100000; since there are 8 bits in total and otherwise it would overflow the 8 bit register (actually happening). I think it's the problem, as the whole port A will be in input mode or hi-z.

Hope being useful
 
2. there is a very long delay after the LED running stop and the LED lights up. is it because of the random instruction require a lot of scan time?

In addition to all the above mentioned misuse of the C language instructions you made, your program lacks of a minimal analysis prior to implementing it. The construction below, in thesis should generate 32 options:

Code:
result = rand();      // generate random value from 0 to 32767
result = result/1000;

But the switch-case on your code considers only 10 options (0 to 9), which means that would be expected a lot of raffles without any update on the lottery display, something in the range of 1/3 ( ~10/32 )
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top