|
|
View previous topic :: View next topic |
Author |
Message |
Laus
Joined: 16 Jan 2016 Posts: 17 Location: Brazil
|
Pwm with pulsin.c base |
Posted: Wed Feb 10, 2016 6:42 am |
|
|
Hello I need to read pulses in 4 pic entries modulate this signal and put it in other 4 outputs I managed to control the high pulse however not low, the pulses are of servo engine 1 to 2ms.The pulse down this very long over 60ms I need 20ms, the PWM works perfectly without pulsin.c code but it does not work but I need it to measure the pulse of time.
Code: |
#include <16F877A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(crystal=20MHz)
#use rs232(BAUD=9600, UART1, ERRORS, BITS=8, PARITY=N) //ensure hardware UART used
//#include <lcd.c>
#include "pulsin.c"
int16 pulse0,pulse1,pulse2,pulse3;
int8 x;
int8 t=80;
void pwm()
{
for(x=0; x<t;x++){
//x=x+1;
if(x>pulse0)
{
output_low(pin_c0);
}
if(x<pulse0)
{
output_high(pin_c0);
}
//**********************************
if(x>pulse0)
{
output_low(pin_c0);
}
if(x<pulse0)
{
output_high(pin_c0);
}
//************************************
if(x>pulse1)
{
output_low(pin_c1);
}
if(x<pulse1)
{
output_high(pin_c1);
}
//************************************
if(x>pulse2)
{
output_low(pin_c2);
}
if(x<pulse2)
{
output_high(pin_c2);
}
//************************************
if(x>pulse3)
{
output_low(pin_c3);
}
if(x<pulse3)
{
output_high(pin_c3);
}
//************************************
if(x>=t) // 20ms
{
x=0;//reset each 20ms
}
}
}
//*******************************************
void main()
{
int16 result0,result1,result2,result3;
//lcd_init();
// delay_ms(500);
while(TRUE)
{
pwm();
//******************input pulses**************************
result0 = pulsin(PIN_B0, 1);
pulse0 = result0*10/300 ; //10 original
//**********************************************
result1 = pulsin(PIN_B1, 1);
pulse1 = result1* 10/300; //10 original
//************************************************
result2 = pulsin(PIN_B2, 1);
pulse2 = result2*10/300 ; //10 original
//************************************************
result3 = pulsin(PIN_B3, 1);
pulse3 = result3 * 10/300; //10 original
//*************************************************
//printf(lcd_putc,"\f%lu %u\n", pulse0,x);
//delay_ms(20);
}
} |
Last edited by Laus on Wed Feb 10, 2016 7:58 am; edited 2 times in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Wed Feb 10, 2016 7:40 am |
|
|
you should post the 'pulsin.c' code or where you got it from. It's not on my version of PCM( 4.xxx).
Jay |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Feb 10, 2016 7:43 am |
|
|
1- format your code with the code button
2- list PULSIN.C as without it your code is NONSENSICAL |
|
|
Laus
Joined: 16 Jan 2016 Posts: 17 Location: Brazil
|
|
Posted: Wed Feb 10, 2016 7:50 am |
|
|
Pulsin.c
Obtained here in the forum
http://www.ccsinfo.com/forum/viewtopic.php?t=42353&highlight=pulsin
Code: |
//***********************************************************
#ifdef __PCB__
#error Pulsin is not supported for the PCB compiler.
#endif
#ifdef __PCD__
#error Pulsin is not supported for the PCD compiler.
#endif
#ifdef __PCM__
#define interrupt_enabled(x) !!(*make8(x,1) & make8(x,0))
#endif
#ifdef __PCH__
#define interrupt_enabled(x) !!(*(make8(x,1) | 0xF00) & make8(x,0))
#endif
#define BYTE_PTR(x) &(int8 *)(x)
// ASM definitions
#define W 0
#define F 1
// Status Register Bits
#define Z 2
#define C 0
#ifdef __PCM__
// Register addresses (16F)
#byte INDF = 0x00
#byte STATUS = 0x03
#byte FSR = 0x04
#endif
#ifdef __PCH__
// Register addresses (18F)
#byte INDF0 = 0xFEF
#byte STATUS = 0xFD8
#byte FSR0H = 0xFEA
#byte FSR0L = 0xFE9
#endif
//---------------------------------------
// #define PULSIN_MAX 60000
#ifdef PULSIN_MAX
#if(PULSIN_MAX > 65535)
#error PULSIN MAX is too High. Maximum value is 65535.
#endif
#endif
//---------------------------------------
#ifdef __PCM__
int16 pulsin(int8 ccs_pin, int8 state)
{
int8 io_port;
#endif
#ifdef __PCH__
int16 pulsin(int16 ccs_pin, int8 state)
{
int16 io_port;
#endif
int8 const bitmask_table[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int8 gie_enabled = FALSE;
int8 bitmask;
int8 flip;
int16 count;
// These variables are used in the ASM code
// and must be located in the same RAM bank.
#locate io_port = 0x30 // Can be 8 or 16 bits
#locate count = 0x32 // 16 bits
#locate state = 0x34
#locate bitmask = 0x35
#locate flip = 0x36
if(interrupt_enabled(GLOBAL))
{
disable_interrupts(GLOBAL);
gie_enabled = TRUE;
}
// Get the I/O Port address and the bitmask from
// the CCS pin number value.
io_port = ccs_pin >> 3;
bitmask = bitmask_table[ccs_pin & 7];
// Set TRIS = input.
#ifdef __PCM__
*(io_port | 0x80) |= bitmask; // For 16F PICs
#endif
#ifdef __PCH__
*(io_port + 0x12) |= bitmask; // For 18F PICs
#endif
#asm
PULSINT:
#ifdef __PCM__
movf io_port, W ; Get port
movwf FSR
#endif
#ifdef __PCH__
movf io_port, W ; Get port lsb
movwf FSR0L
movf BYTE_PTR(io_port) +1, W ; Get port msb
movwf FSR0H
#endif
movf bitmask,w
clrf flip ; Preset state tracking
btfss state, 0 ; State tracking preset for flip
movwf flip ; Set state to bit mask
call statecnt ; Wait for idle state
btfsc STATUS, Z ; If timeout then it's over
goto done
call statecnt ; Wait for starting edge
btfsc STATUS, Z ; If timeout then it's over
goto done
call statecnt ; Do the count
goto done
//--------------------------------------------------
statecnt:
movf bitmask, W ; Flip state each time through here
xorwf flip, F
#ifdef PULSIN_MAX
movlw ((-(PULSIN_MAX)) + 1) ; Start counter -PULSIN_MAX + 1
movwf count
movlw (((-(PULSIN_MAX)) + 1) >> 8)
movwf BYTE_PTR(count) + 1
#else
movlw 1
movwf count
clrf BYTE_PTR(count) + 1
#endif
statecntloop: ; Takes 10 usec
#ifdef __PCM__
movf INDF, W ; 1 Read Port with INDF
#endif
#ifdef __PCH__
movf INDF0, W ; 1 Read Port with INDF0
#endif
andwf bitmask, W ; 1 Mask it with bitmask
xorwf flip, W ; 1 Mix with desired state
btfss STATUS, Z ; 2 / 1
#ifdef PULSIN_MAX
goto statecntexit ; 0 / 2 No longer in state
#else
return ; 0 / 2 No longer in state
#endif
incf count, F ; 1 Increment counter
btfsc STATUS, Z ; 1 / 2
incfsz BYTE_PTR(count) + 1, F ; 1 / 2
goto statecntloop ; 2 / 0
return ; 0 / 2 Counter overflow
#ifdef PULSIN_MAX
statecntexit:
movlw PULSIN_MAX ; Normalize count
addwf count, F
movlw PULSIN_MAX >> 8
btfsc STATUS, C
addlw 1
addwf BYTE_PTR(count) + 1, F
bcf STATUS, Z ; Indicate no overflow
return
#endif
done:
#endasm
if(gie_enabled)
{
enable_interrupts(GLOBAL);
}
return(count);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Wed Feb 10, 2016 8:07 am |
|
|
Perfect ! Now we can help....
Knowing PCM created it is has to work.....
first start off with ONE servo,get it working..then 2,3,4
It's a LOT easier and 'proper technique' to start small, build on working code.
Jay |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Feb 10, 2016 8:21 am |
|
|
by "servo engine" i believe you mean hobby style pulse width controlled servo right ?
PCM's program was created for impaired PICS that have no CCP capability
but the 877 DOES have the hardware.
have you read the CCP section of the
16f877 datasheet to see how it could help you?
what IS your project and what are you trying to control?
Your post is very hard to make sense of unless you explain what your project IS and what you are controlling..
add some DIMENSION please |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Wed Feb 10, 2016 8:46 am |
|
|
I _think_ he's trying to read 4 input signals ( 1-2ms) and then control 4 RC servos with the data..
It looks like he's bodged code from several sources....
I understand English isn't everyone's 1st language but we really need a better description of the project.
He should start with one input-> PIC-->one output
Jay |
|
|
Laus
Joined: 16 Jan 2016 Posts: 17 Location: Brazil
|
|
Posted: Wed Feb 10, 2016 9:02 am |
|
|
ok I'll work the signal 1 radio control RC receiver, PPM signal and the pic increase or decrease the duration of the positive pulse, the only problem and that I'm not able to control the negative part of the pulse with the above code, not to use the CCP as are 4 different signals |
|
|
Laus
Joined: 16 Jan 2016 Posts: 17 Location: Brazil
|
|
Posted: Wed Feb 10, 2016 9:09 am |
|
|
This part controls the negative pulse time should be in 20ms but this around 60ms.
If you use this code in alone I have a PPM signal 1 and 2ms 50Hz.
Code: | {
for(x=0; x<t;x++){
//x=x+1;
if(x>pulse0)
{
output_low(pin_c0);
}
if(x<pulse0)
{
output_high(pin_c0);
}
//************************************
if(x>=t) // 20ms
{
x=0;//reset each 20ms
}
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Wed Feb 10, 2016 9:36 am |
|
|
Take a deep breath, and step back.
What you currently have is never properly going to work.
Bits of code from various locations assembled without any understanding of what they do, and more importantly of how they will interact.
Big problem is that every single direction through a loop like this will differ slightly in time. So if you tweak everything to get your 20mSec, then you just change one thing (one of the time values), the timing will then be wrong....
The delay while the values are read, will also change according to the incoming pulses. and result in even more variation. This is why you are seeing the timing error for your 60mSec.
You need to be switching to actually using a hardware clock, and effectively multi-tasking. Use the hardware CCP's to generate the output pulses. I posted single pulse CCP code to generate a servo pulse only a few weeks ago, and for what you want (with the pulses sequential), this can very easily be modified to handle four pulses rather than one.
Then realise that 'pulsein', was published as a 'bodge' to allow a pulse width to be measured on a chip that did not have a CCP. To do the measurement without affecting the output pulse, I'd be suggesting you need to look at using the interrupt on change, on the four input bits (so feeding them to B4 to B7), and then recording the value from a single timer to measure the widths. The main loop can then sit and when these values have updated, calculate the new times, and feed these into the code for the outputs. |
|
|
Laus
Joined: 16 Jan 2016 Posts: 17 Location: Brazil
|
|
Posted: Wed Feb 10, 2016 10:05 am |
|
|
The operation of the code was understood I use this PWM in several other codes, the part that is not mine and the pulsin.c .The intention was to replace a reading done by a adc, and a pot for the values returned by pulsin code and thus controlling the PWM. I posted here because after several attempts with other PWM until even with Timer use not got success the pulse of negative time ever and larger than expected with any implemented PWM |
|
|
Laus
Joined: 16 Jan 2016 Posts: 17 Location: Brazil
|
|
Posted: Wed Feb 10, 2016 10:10 am |
|
|
And how sometimes the solution is simple and this is our view but we could not see by some oversight, asked for help here. But I see the PWM is really incompatible with the control made through the code pulsin. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Wed Feb 10, 2016 10:15 am |
|
|
No.
The point is that pulsin takes _time_, and this varies according to the pulse widths involved, and the phase relationship between the pulses being tested (given that you test multiple pulses in sequence).
Your PWM code won't maintain accurate gaps, if anything in the loop involved changes in time.
You need to generate the timing between the pulses here using a timer, so that it becomes independant of the other things happening. |
|
|
Laus
Joined: 16 Jan 2016 Posts: 17 Location: Brazil
|
|
Posted: Wed Feb 10, 2016 10:30 am |
|
|
The problem is that the pulsin disable the timer sometimes and this causes more errors in the PWM. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Feb 10, 2016 11:21 am |
|
|
I'm just plain lost.
Maybe some pictures/diagrams/ASCIIart showing us what you are trying to achieve will help.
Then we can come up with alternative ways of doing the job in hand.
Mike |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|