|
|
View previous topic :: View next topic |
Author |
Message |
Khansokhua
Joined: 06 Nov 2021 Posts: 92
|
|
Posted: Mon Mar 20, 2023 10:54 am |
|
|
Ttelmah wrote: | You big remaining issue, is using printf.
printf, is code to 'format' values into different output layouts. You are telling
it to send the value as ASCII text. So an internal value of 123, with be sent
as the text " 123". Now your receive program knows nothing about ASCII,
and read a single character. So it'll see a space, then '1', then '2', then '3'.
You need to just use 'putc' to put the single binary character representing
'123', and then the receive getc, will receive what it expects.... |
I did Code: | unsigned int8 valor_adc=read_adc( );
putc(valor_adc); |
but still same, jittering. There is a difference that motor doesn't move at max or min point of potentiometer. I also did Code: | putc(255); // stops at 180 degree
putc(0);// other values like '0' jittering | Adc values is being read but what causes this complication? What should I do? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Mon Mar 20, 2023 11:46 am |
|
|
Your servo writes take time, and have delays between then. Your putc;s
need the same. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Mon Mar 20, 2023 12:34 pm |
|
|
Historically, RC servos ran at 50 Hz....so you should have 20ms between commands... |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Mon Mar 20, 2023 12:40 pm |
|
|
I'd break everything into several parts.
Reading ADC: a few posts up I saw you are testing for exact values. Don't. There is every chance ADC will read different values for the same position of a pot. Instead use ranges, as many as you need for commands. If a pot reads between 0 and 50, that is full left. 51 - 100 something else. You get the idea. Then set a variable Command accordingly (you chose names, ranges and number of commands, of course). This can be tested with some LED's on the master PIC. If the correct LED lights up according to the pot position, this is done.
Communication: Hook the PIC's together or even hook the same PIC if it has two UART modules. Do use interrupt on the receiving side. Check if what you send appears on the receiving side and how it appears, using a buffer, debugger and one break-point or by re-sending it out on a terminal. Only my style, of course, but I'd send out short command strings, not raw ADC values. Based on a Command value, let's say FLFT. Repeat the exercise with LED's, this time on the slave side. All the parsing can be done inside isr routine, very, very fast. Main only does anything if something good arrived on the serial. |
|
|
Khansokhua
Joined: 06 Nov 2021 Posts: 92
|
|
Posted: Mon Mar 20, 2023 2:12 pm |
|
|
temtronic wrote: | Historically, RC servos ran at 50 Hz....so you should have 20ms between commands... |
Ttelmah wrote: | Your servo writes take time, and have delays between then. Your putc;s
need the same. |
Uunhappily |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Tue Mar 21, 2023 1:38 am |
|
|
Part of this is what people have been telling you from the start.
You need to separate the receive from the update. Have a master loop,
that does the parsing, and the servo update. Running continuously.
Then have the serial receive into a buffer using the interrupt.
Each time the servo loop goes round, if a character is in the buffer it
reads this and changes the servo. If not it leaves the servo where it is.
The position then becomes stable. You send a character to move to a new
position, when you want, and when this is received, the servo moves on
the next loop. Provided you don't send movements faster than the loop,
the two operations become independant of each other. |
|
|
Khansokhua
Joined: 06 Nov 2021 Posts: 92
|
#int_rda |
Posted: Wed Mar 22, 2023 5:33 am |
|
|
I was trying rda interrupt, I send a constant data "putc(255);" with a button.
First press D1 led is blinking, but after more than ten push led is still blinking.
Code: | #include <16F877A.h>
#FUSES HS, NOWDT,NOPROTECT, NOPUT , NOLVP, BROWNOUT
#use delay(clock=20000000)
#use rs232(baud=4800,BITS=8, PARITY=N,XMIT=pin_C6, RCV=pin_C7, STREAM=SPIC,ERRORS)
#use standard_io(D)
#define use_servo_1
#define servo_1 pin_d0
#include <servo_st.c>
#include <map_function.c>
int a=0;
#int_rda
void isr(){
if(a>=10) {
output_low(pin_d1);
a=10;
}
if(a<10){output_high(pin_d1);
a++;}
disable_interrupts(int_rda);
}
void main()
{
enable_interrupts(int_rda);
enable_interrupts(global);
servo_init();
while(TRUE)
{
delay_ms(100);
unsigned int8 valor =getc();
unsigned int8 valor_a=map(valor ,0,255,0,180);
delay_ms(2000);
servo_1_write(valor_a);
delay_ms(2000);
}
} |
|
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Wed Mar 22, 2023 11:09 am |
|
|
You got the RDA interrupt wrong. The received data is and must be read there, not in any loop in main(). I wrote something, see if it does the trick. Don't press the button faster then every 4 seconds, if you decide to keep both delays. Un-comment functions.
Code: |
#include <16F877A.h>
#FUSES HS, NOWDT,NOPROTECT, NOPUT , NOLVP, BROWNOUT
#device ADC=10
#use delay(crystal=20000000)
#use rs232(baud=4800,BITS=8, PARITY=N,XMIT=pin_C6, RCV=pin_C7, STREAM=SPIC,ERRORS)
unsigned int8 valor = 0;
unsigned int8 valor_a;
#INT_RDA
void RDA_isr(void)
{
valor =getc(); // read and store received data. It also clears interrupt flag.
output_toggle(pin_d1); // turn diode on or off every time you receive something
}
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE)
{
// delay_ms(100);
// unsigned int8 valor =getc(); // if you use interrupt, this doesn't belong here
// valor_a=map(valor ,0,255,0,180); // commented because I don't have that function, uncomment
delay_ms(2000); // why so much delay here?
// servo_1_write(valor_a); // uncomment
delay_ms(2000);
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Wed Mar 22, 2023 12:26 pm |
|
|
comment
4800 baud is about 2ms per byte (character sent )
so if the 'transmitter' continuously sent data, it's 10X faster than what the RC servo can understand.
There is no need to send faster than 1 command every 20ms,and in fact it can 'confuse' the RC servo. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Wed Mar 22, 2023 12:45 pm |
|
|
Yes. Only me again, but I'd also do the transmitter timing via a timer interrupt. 20ms or so tick. Read ADC. Calculate the value you wish to send, send it out. But if this is the only thing master does, a loop with a delay is more than fine. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Thu Mar 23, 2023 12:50 am |
|
|
Yes.
It's critical to understand that trying to do things faster than they can
actually 'happen' will actually make things occur slower rather than faster. |
|
|
Khansokhua
Joined: 06 Nov 2021 Posts: 92
|
|
Posted: Thu Mar 23, 2023 1:41 pm |
|
|
I tried something. I though I use just two data buffered from transmitter and try compare them each other.
But it seems not going well. How can I improve this work?
Code: | #include <16F877A.h>
#FUSES HS, NOWDT,NOPROTECT, NOPUT , NOLVP, BROWNOUT
#use delay(clock=20000000)
#use rs232(baud=4800,BITS=8, PARITY=N,XMIT=pin_C6, RCV=pin_C7, STREAM=SPIC,ERRORS)
#use standard_io(D)
#define use_servo_1
#define servo_1 pin_d0
#include <servo_st.c>
#include <map_function.c>
int order=0;
char buffer[];
#int_rda
void isr(){
buffer[order] =getc();
servo_init();
delay_ms(20);
if(buffer[order+1]==buffer[order]){
servo_1_write(buffer[order]);
}
if(buffer[order+1]<=buffer[order]){
servo_1_write(buffer[order]);
}
if(buffer[order+1]>=buffer[order]){
servo_1_write(buffer[order+1]);
}
order++;
if(order==2)
order=0;
}
void main()
{
enable_interrupts(int_rda);
enable_interrupts(global);
servo_init();
while(TRUE)
{
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Thu Mar 23, 2023 2:56 pm |
|
|
1st thing. Get rid of the delay_ms(20) inside the ISR ! You should never have any delay ,of any kind in an ISR. Also no printing or 'fancy' math.
You receive a character, save it, set a 'flag', then exit.
Main() will test the 'flag' and then do whatever is necessary.
2nd thing. Use /modify the CCS supplied SISR.C code. It works and most everyone here can help.
Not to sure why you call servo_init() within the ISR. Normally an 'init' is done once at the beginning of a program. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Thu Mar 23, 2023 4:49 pm |
|
|
If I understood correctly, you are trying to control a servo over serial. I'm saying this because your questions are jumping around a bit. I have some of my own:
1. Servo motor works on your master PIC?
2. You can control servo via a pot on your master?
3. Do you receive what you send from master to slave over serial? Or better, can you read it?
About interrupts. For a property, three magic words are LOCATION, LOCATION, LOCATION. For interrupts, there are also three: SPEED, SPEED, SPEED. You don't do any delays or complicated things there, ever. No delays, no math. Your main() must do that. You dumped everything into RDA_ISR. With a 20ms delay there you could loose 10 or more commands from master and never even know it. |
|
|
Khansokhua
Joined: 06 Nov 2021 Posts: 92
|
|
Posted: Fri Mar 24, 2023 5:00 am |
|
|
PrinceNai wrote: | If I understood correctly, you are trying to control a servo over serial. I'm saying this because your questions are jumping around a bit. I have some of my own:
1. Servo motor works on your master PIC?
2. You can control servo via a pot on your master?
3. Do you receive what you send from master to slave over serial? Or better, can you read it?
|
1.Servo motor works on slave
2.yes(but not expected)
3.I guess, I receive and read somethings but anormal crazy movements happen |
|
|
|
|
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
|