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.

Digital Fat Calliper Sensor

Status
Not open for further replies.
Hi,

For the fat matrix scale, there consists of 64 thin strips. I found that the distance between 2 strip is 0.78mm. My question is, how should I write the programming code so that the microcontroller can get the distance?
I really need help from you all. Thanks.

Vivian
 
For the fat matrix programming code, I found that you stated there as 'enable weak pull-ups on port B' for the coding of nRBPU=0, but from the PIC16F887 manual, it state that :

bit 7-0 WPUB<7:0>: Weak Pull-up Register bit
1 = Pull-up enabled
0 = Pull-up disabled

So, is that means the coding should change to nBRPU=1 in order to enable the weak pull-up? And I try to use the microC to run the code, it shows that ' Undeclared identifier 'nRBPU' ' for the nRBPU=0.
If nRBPU isn't found, try RBPU = 0; it is the top bit in OPTION_REG in any case. The WPUB bits default to 1, so you don't need to worry about them.

For the fat matrix scale, there consists of 64 thin strips. I found that the distance between 2 strip is 0.78mm. My question is, how should I write the programming code so that the microcontroller can get the distance?
I really need help from you all. Thanks.
The calliper draws an arc with the moving arm; therefore you should get the total angle spanned by the 64 switches and divide by 64. This will be the effective angle per switch.

To calculate the skin thickness you also need the distance from the calliper's rotation point to the end of the arm (that end that touches the skin). You then apply some maths (https://www.mathopenref.com/chord.html) and get the chord length, which is the skin thickness. Use a 64 entry lookup table rather than calculating the values in your code.
 
Hello,

I want to shows the value of age and gender in my LCD. And the user can change the value of age and gender by pressing the tact switch. Can I know how should I program my LCD so that it's value can be adjusted??


Vivian
 
Hi,

fat matrix 2.jpg

I have question about this fat matrix charliplexing. Assume one of the button in D5 is pressed, how the charlieplexing works in order to send the signal to the microcontroller? How the microcontroller know which of the button is pressed??
I really need to know it, please help me..thanks!

Vivian
 
Hi Doug,

For the fat matrix coding that you have wrote, how to make the return value to be displayed on the LCD display?
Please reply me, I really need your help.
Thanks a lot.


Vivian
 
You need to learn how to program in C first.

To display information on the LCD, you will first need to initialise it, then write the numeric data (the value returned from the readCalliper() function converted to ASCII characters). Hopefully someone can provide you with direction in this regard.
 
#include <stdint.h>

unsigned char i;
unsigned char j;
unsigned char pv;


const uint8_t pow2[8] = {1,2,4,8,16,32,64,128}; //allows fast way to get
//a power of two value
uint8_t readCalliper()
{
OPTION_REG.NOT_RBPU = 0; //enable weak pull-ups on PORTB
TRISB = 0xFF; //all PBO-1(8pin) floating high
PORTA&=0xF0; //set the output value of pins on PEO-1 to 0
//these pins are kept as inputs,excepts when one is driven low
//get ready to pull low on PEO-1

//first try pulling each pin of PEO-1 low in succession

for (i=0;i<4;i++)
{
TRISA = (TRISA&0xF0) | (~pow2&0x0F); //set PEO-1(4pin) as output so
//that it can be driven low
//set a single bit as output (forced low)
delay_us(5);
pv=PORTB;
if (pv != 0xFF)
{
for(j=0;j<8;j++)
{
if(!(pv&1))
return i*16+j;
pv>>=1;
}
}
}

TRISA |= 0x0F; //all PEO-1 floating high
PORTB=0; //get ready to pull low on PBO-1

for (j=0;j<8;j++)
{
TRISB=~pow2[j]; //set PBO-1 pins as output so
//that it can be driven low
delay_us(5);

pv=PORTA;
if (pv&0x0F !=0x0F) //just checking if one of the
//PEO-1 pins have been pulled low
{
for(i=0;i<4;i++)
{
if(!(pv&1))
return i*16+8*j;
pv>>=1;
}
}
}
return 0; //no valid reading
}

//LCD Module Connections

sbit LCD_RS at RD4_bit;
sbit LCD_EN at RD5_bit;
sbit LCD_D4 at RD0_bit;
sbit LCD_D5 at RD1_bit;
sbit LCD_D6 at RD2_bit;
sbit LCD_D7 at RD3_bit;
sbit LCD_RS_Direction at TRISD4_bit;
sbit LCD_EN_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD0_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D7_Direction at TRISD3_bit;





void main()
{


Lcd_Init();
Lcd_Out(1,2,"25");
Lcd_Out(1,6,"F");
Lcd_Out(1,13,"BF%");
Lcd_Out(2,2,pv);

}



This is the editted code. But I failed to show which button has been pressed.
 
It's good to see that you have access to an LCD library. In https://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/lcd_library.htm, they make sure to configure all analogue pins (e.g. comparator and ADC) as digital - make sure to do that for all the pins you are using for the matrix and for the LCD.

To display the caliper value, I'd perhaps use the following:
Code:
uint_t value = readCalliper();
char valueText[4] = {'0' + (value/100), '0' + ((value / 10) % 10), '0' + (value % 10), 0};
Lc_Out(1,8,valueText);
 
Last edited:
Hi Doug,

I tried to use your code, but it come out with an error, which is 'Const expression expected'.

#include <stdint.h>

unsigned char i;
unsigned char j;
unsigned char pv;


const uint8_t pow2[8] = {1,2,4,8,16,32,64,128}; //allows fast way to get a power of two value
uint8_t readCalliper()
{
OPTION_REG.NOT_RBPU = 0; //enable weak pull-ups on PORTB
TRISB = 0xFF; //all PBO-1(8pin) floating high
PORTA&=0xF0; //set the output value of pins on PEO-1 to 0 these pins are kept as inputs,excepts when one is driven low
//get ready to pull low on PEO-1

//first try pulling each pin of PEO-1 low in succession

for (i=0;i<4;i++)
{
TRISA = (TRISA&0xF0) | (~pow2&0x0F); //set PEO-1(4pin) as output so that it can be driven low
//set a single bit as output (forced low)
delay_us(5);
pv=PORTB;
if (pv != 0xFF)
{
for(j=0;j<8;j++)
{
if(!(pv&1))
return i*16+j;
pv>>=1;
}
}
}

TRISA |= 0x0F; //all PEO-1 floating high
PORTB=0; //get ready to pull low on PBO-1

for (j=0;j<8;j++)
{
TRISB=~pow2[j]; //set PBO-1 pins as output so that it can be driven low
delay_us(5);

pv=PORTA;
if (pv&0x0F !=0x0F) //just checking if one of the PEO-1 pins have been pulled low
{
for(i=0;i<4;i++)
{
if(!(pv&1))
return i*16+8*j;
pv>>=1;
}
}
}
return 0; //no valid reading

}

//LCD Module Connections

sbit LCD_RS at RD4_bit;
sbit LCD_EN at RD5_bit;
sbit LCD_D4 at RD0_bit;
sbit LCD_D5 at RD1_bit;
sbit LCD_D6 at RD2_bit;
sbit LCD_D7 at RD3_bit;
sbit LCD_RS_Direction at TRISD4_bit;
sbit LCD_EN_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD0_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D7_Direction at TRISD3_bit;



unsigned char value=readCalliper();
char valueText[4]={'0'+(value/100),'0'+((value/10)%10),'0'+(value%10)};


void main()
{
ANSEL = 0; // Configure AN pins as digital I/O
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;

Lcd_Init();
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,2,"25");
Lcd_Out(1,6,"F");
Lcd_Out(1,13,"BF%");
Lcd_Out(2,8,valueText);




}
 
The lines of code I provided would go inside the main() function. I omitted the final zero in the declaration of valueText[] (changed above).

If you still get the same compilation error, then you can use the following in place of the declaration of valueText[].
Code:
char valueText[4];
valueText[0] = '0' + (value/100);
valueText[1] = '0' + ((value / 10) % 10);
valueText[2] = '0' + (value % 10);
valueText[3] = 0;

If you want to continuously display the changing value, you'll have to place the readCalliper() and Lcd_Out() functions in a loop (and include a delay).
 
Hi Doug,

The error 'Const expression expected' is come from the code:
unsigned char value=readCalliper();
Before that you are writing 'uint_t value=readCalliper() ', but it come out with the error ' Undeclared identifier 'uint_t' in expression'.
 
That code would go in the main() function.

uint8_t is the same as unsigned char if #include <stdint.h> is included in the code.
 
Hi Doug,

What is this refer to?
char valueText[4];
valueText[0] = '0' + (value/100);
valueText[1] = '0' + ((value / 10) % 10);
valueText[2] = '0' + (value % 10);
valueText[3] = 0;

The code can be run now. But the number of button pressed does not display out.
Attached pic is the design when perform the simulation
Untitled.jpg
 
#include <stdint.h>

unsigned char i;
unsigned char j;
unsigned char pv;


const uint8_t pow2[8] = {1,2,4,8,16,32,64,128}; //allows fast way to get a power of two value
uint8_t readCalliper()
{
OPTION_REG.NOT_RBPU = 0; //enable weak pull-ups on PORTB
TRISB = 0xFF; //all PBO-1(8pin) floating high
PORTA&=0xF0; //set the output value of pins on PEO-1 to 0 these pins are kept as inputs,excepts when one is driven low
//get ready to pull low on PEO-1

//first try pulling each pin of PEO-1 low in succession

for (i=0;i<4;i++)
{
TRISA = (TRISA&0xF0) | (~pow2&0x0F); //set PEO-1(4pin) as output so that it can be driven low
//set a single bit as output (forced low)
delay_us(5);
pv=PORTB;
if (pv != 0xFF)
{
for(j=0;j<8;j++)
{
if(!(pv&1))
return i*16+j;
pv>>=1;
}
}
}

TRISA |= 0x0F; //all PEO-1 floating high
PORTB=0; //get ready to pull low on PBO-1

for (j=0;j<8;j++)
{
TRISB=~pow2[j]; //set PBO-1 pins as output so that it can be driven low
delay_us(5);

pv=PORTA;
if (pv&0x0F !=0x0F) //just checking if one of the PEO-1 pins have been pulled low
{
for(i=0;i<4;i++)
{
if(!(pv&1))
return i*16+8*j;
pv>>=1;
}
}
}
return 0; //no valid reading
}


//LCD Module Connections

sbit LCD_RS at RD4_bit;
sbit LCD_EN at RD5_bit;
sbit LCD_D4 at RD0_bit;
sbit LCD_D5 at RD1_bit;
sbit LCD_D6 at RD2_bit;
sbit LCD_D7 at RD3_bit;
sbit LCD_RS_Direction at TRISD4_bit;
sbit LCD_EN_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD0_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D7_Direction at TRISD3_bit;

void main()
{
unsigned char value = readCalliper();
char valueText[4];
valueText[0] = '0' + (value/100);
valueText[1] = '0' + ((value / 10) % 10);
valueText[2] = '0' + (value % 10);
valueText[3] = 0;

ANSEL = 0; // Configure AN pins as digital I/O
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;

Lcd_Init();
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,2,"25");
Lcd_Out(1,6,"F");
Lcd_Out(1,13,"BF%");
Lcd_Out(2,2,valueText);





This is the code that use to simulate the circuit.
 
Code:
void main()
{

ANSEL = 0; // Configure AN pins as digital I/O
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;

Lcd_Init();
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,2,"25");
Lcd_Out(1,6,"F");
Lcd_Out(1,13,"BF%");

while(1)
{
   // get new value
   unsigned char value = readCalliper();
   char valueText[4];
   valueText[0] = '0' + (value/100);
   valueText[1] = '0' + ((value / 10) % 10);
   valueText[2] = '0' + (value % 10);
   valueText[3] = 0;

   // display new value
   Lcd_Out(2,2,valueText);

   // throttle update rate to stop the display from blurring
   Delay_ms(100);
}
 
Hi Doug,

Thanks for the edited code. But it still no number of button display when I pressed the button. Will it because there is no power supply to the fat matrix? Or because no output is send to the LCD?
Sorry to disturb.
 
Hi,

Below is my problem:
1) The number of button pressed will recount start from 0 when reached diode 5-8.

Attached is my edited circuit design:
gh.jpg

And this is the picture for the problem occured:
Button on diode 1 is pressed: fd.jpg


Button on diode 5 is pressed: jj.jpg

Below is the code I use to run the simulation:
unsigned char i;
unsigned char j;
unsigned char pv;


const uint8_t pow2[8] = {1,2,4,8,16,32,64,128}; //allows fast way to get a power of two value
uint8_t readCalliper()
{
OPTION_REG.NOT_RBPU = 0; //enable weak pull-ups on PORTB
TRISB = 0xFF; //all PBO-1(8pin) floating high
PORTA&=0xF0; //set the output value of pins on PEO-1 to 0 these pins are kept as inputs,excepts when one is driven low
//get ready to pull low on PEO-1

//first try pulling each pin of PEO-1 low in succession

for (i=0;i<4;i++)
{
TRISA = (TRISA&0xF0) | (~pow2&0x0F); //set PEO-1(4pin) as output so that it can be driven low
//set a single bit as output (forced low)
delay_us(5);
pv=PORTB;
if (pv != 0xFF)
{
for(j=0;j<8;j++)
{
if(!(pv&1))
return i*8+j;
pv>>=1;
}


}
}

TRISA |= 0x0F; //all PEO-1 floating high
PORTB=0; //get ready to pull low on PBO-1
for (j=0;j<8;j++)
{
TRISB=~pow2[j]; //set PBO-1 pins as output so that it can be driven low
delay_us(5);

pv=PORTA;
if (pv&0x0F !=0x0F) //just checking if one of the PEO-1 pins have been pulled low
{
for(i=0;i<4;i++)
{
if(!(pv&1))
return i*16+8*j;
pv>>=1;
}
}
}
return 0; //no valid reading
}
 

Attachments

  • fd.jpg
    fd.jpg
    47.8 KB · Views: 219
  • jj.jpg
    jj.jpg
    46.5 KB · Views: 221
Last edited:
Hi Vivian,

Sorry, but I can't run the design you provided as there seems to be limitations in the demo version of Proteus.

I can tell you that the resistors connected to PORTA should be connected to 5V and not to ground as you have done. The direction of the diodes should also be corrected.

I will have a look at the code at a later date to see if there are any obvious bugs in the function I provided.

Cheers,
Doug
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top