Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC code help (arrays)

Status
Not open for further replies.

cielo

New Member
I'm working on a project and can't seem to think of a solution to my situation. I hope the following description is clear.

I've got a queue system with four boxes (each has a sw and gr/rd leds) connected to the 16F84. If someone wants to "go", the switch is in the "next" state; otherwise all red leds are lit in the "done" state. When the switch is in the next state, the green led turns on while the red led turns off. If a box is in the next state with the green led lit and the other(s) flip their switch to next, they remain in queue with the red led remaining lit. Once the first box turns to done, the green led lights from the box that's next in line (and red turns off).

Right now, the boxes toggle left-to-right instead of going to the box that went "next" first. i.e. box1 green led is lit and box3,2,4 all go into "next" state. when box1 is done, box2 is lit, not three.

Here's my code:
Code:
/*Inputs: PB.B0-B3
  Next state: logic 0
  Done state: logic 1

  Outputs: Green LEDs: PB.B4-B7 Red LEDs: PA.B0-B3
  LEDs on with logic 0
*/



#include <P16F84.h>
#include <delays.h>

void main()
{
	TRISB = 0x0F;
	TRISA = 0x00;
	unsigned char order[4] = {0, 0, 0, 0};
	unsigned char i;
	
	
	while(1)
	{
	
	if (PB.B0 == 1 && PB.B1 == 1 && PB.B2 == 1 && PB.B3 == 1) //if all switches are in done state, turn on all red leds
	{
	PA.B0 = 0;
	PA.B1 = 0;
	PA.B2 = 0;
	PA.B3 = 0;
	}
	
	if (PB.B0 == 0)				//run loop if sw1 is in next state
		for(i=0; i<=3; i++)
		{
		if (order[i] == 0 && order[i] != 1) 	//if in first loop, declare sw1 next to be order 1
			order[i] == 1;		
		break;
		}
	if (PB.B1 == 0)				//run loop if sw2 is in next state
		for(i=0; i<=3; i++)
		{
		if (order[i] == 0 && order[i] != 2)	//if in first loop, declare sw2 next to be order 2
			order[i] == 2;		
		break;
		}
	if (PB.B2 == 0)				//run loop if sw3 is in next state
		for(i=0; i<=3; i++)
		{
		if (order[i] == 0 && order[i] != 3)	//if in first loop, declare sw3 next to be order 3
			order[i] == 3;
		break;
		}
	if (PB.B3 == 0)				//run loop if sw4 is in next state
		for(i=0; i<=3; i++)
		{
		if (order[i] == 0 && order[i] != 4)	//if in first loop, declare sw4	next to be order 4
			order[i] == 4;
		break;
		}
	if (order[0] = 1)		//order 1
	{
		while (PB.B0 != 1) {	//verifying sw is not in done state
			PB.B4 = 0;	//turning on green led

			PB.B5 = 1;	//turn off all other green leds
			PB.B6 = 1;
			PB.B7 = 1;
		
			PA.B0 = 1;	//turn off red led
			PA.B1 = 0;	//turn on all other red leds
			PA.B2 = 0;
			PA.B3 = 0; };
	}
	if (order[0] = 2)		//order 2
	{
		while (PB.B1 != 1) {		
			PB.B5 = 0;
			
			PB.B4 = 1;
			PB.B6 = 1;
			PB.B7 = 1;
			
			PA.B1 = 1;
			PA.B0 = 0;
			PA.B2 = 0;
			PA.B3 = 0; };
	}
	if (order[0] = 3)		//order 3
	{
		while (PB.B2 != 1) {		
			PB.B6 = 0;
			
			PB.B4 = 1;
			PB.B5 = 1;
			PB.B7 = 1;
			
			PA.B2 = 1;
			PA.B1 = 0;
			PA.B0 = 0;
			PA.B3 = 0; };
	}
	if (order[0] = 4)		//order 4
	{
		while (PB.B3 != 1) {		
			PB.B7 = 0;
			
			PB.B4 = 1;
			PB.B5 = 1;
			PB.B6 = 1;
			
			PA.B3 = 1;
			PA.B1 = 0;
			PA.B2 = 0;
			PA.B0 = 0; };
	}	
		order[0] = order[1];	//first element assigned to order 1 
		order[1] = order[2];	//order 1 assigned to order 2
		order[2] = order[3];
		order[3] = 0;		//clear array
		PORTA = 1;		//turn off all leds
		PB.B4 = 1;
		PB.B5 = 1;
		PB.B6 = 1;
		PB.B7 = 1;
	};
}
I think I need to use another array to store the order, though I can't think of effective methods w/o long if statements. Any help is much appreciated. Thanks!!!
Jon
 
A circular buffer would do the trick. All you do is you have your array and two pointers or indexes - one for in and one for out. Each time you add a element you put it in the in location and increment the in pointer. To take stuff out you grab it from the out location and increment the pointer. if the two pointer are equal there is nothing in the buffer.

This code is untested but it'll give you the basic idea.
Code:
unsigned char order[4] = {0, 0, 0, 0}; 
unsigned char InIndex, OutIndex = 0;

void AddElement(unsigned char val)
{
  order[InIndex] = Val;  /* add new value to buffer */
  InIndex++;                /*increment index*/
  InIndex &= 0x03;       /* mask off bits above numbers 0-3 to make Index wrap around */
}

unsigned char RemoveElement()
{
  unsigned char temp;
  temp = order[OutIndex];
  OutIndex++;
  OnIndex &= 0x03;       /* mask off bits above numbers 0-3 to make index wrap around */
  return temp;
}

unsigned char IsBufferEmpty()
{
  if (OutIndex == InIndex)
  {
     return 1;
  }
  else
  {
     return 0;
   }
}

I like to put the array and index into a struct and pass a pointer to that struct into each buffer related function call - its a bit slower but it lets you use the same function calls for more than one buffer.

The masking line - OnIndex &= 0x03; - only works if you have a power of 2 for your array size. Otherwise you have to use: if (index >= BUFFERSIZE) to set the index back to 0;
 
Thanks! I tried ammending my code with indexing but after being unsuccessful, I started over with a different method. It works now, luckily...thanks again!
Jon
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top