![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
Read-Write-Modify issues |
Posted: Sat Dec 24, 2016 11:14 am |
|
|
Good day to everyone and happy holidays!
I have been missing for a long time, thank you for all your help so far and I have another interesting issues that I need solved :D.
Despite that I understand RWM issues, I want to know is there any way to use input_x and output_x functions if I put a delay of 1ms before them? Despite that I believe that should be enough I am not certain. Does it depend on the current microcontroller, the clock speed, the technology flash or EEPROM and others if there are any?
Thank you for your support! _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Sat Dec 24, 2016 3:06 pm |
|
|
you should post the PIC type you're using(some handle RMW differently) as well as a small compilable program to show us what you want to do.
As well, type of speed you need,what's being controlled, etc.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Sat Dec 24, 2016 3:25 pm |
|
|
I am trying to understand how to do it by myself, not to need to ask every time will RWM issues work on this microcontroller or not. But here is what is you asked for.
Code: |
//We display the value of 1 sensor on the 7 segment display. We have 4 //sensors in total.
#include <16F690.h>
#fuses MCLR, NOPROTECT, NOWDT, INTRC_IO
#use delay(clock=4M)
unsigned int8 Output;
unsigned int8 i;
unsigned int8 Sensor_PIN_A0, Potentiometer_PIN_A1, Sensor_PIN_A2, Potentiometer_PIN_A3;
unsigned int8 FinalFormOfThePORTCOutput[60] =
{
0b00000000, // 0
0b00000001,
0b00000010,
0b00000011,
0b00000100,
0b00000101,
0b00000110,
0b00000111,
0b00001000,
0b00001001,
0b00010000, // 10
0b00010001,
0b00010010,
0b00010011,
0b00010100,
0b00010101,
0b00010110,
0b00010111,
0b00011000,
0b00011001,
0b00100000, // 20
0b00100001,
0b00100010,
0b00100011,
0b00100100,
0b00100101,
0b00100110,
0b00100111,
0b00101000,
0b00101001,
0b00110000, // 30
0b00110001,
0b00110010,
0b00110011,
0b00110100,
0b00110101,
0b00110110,
0b00110111,
0b00111000,
0b00111001,
0b01000000, // 40
0b01000001,
0b01000010,
0b01000011,
0b01000100,
0b01000101,
0b01000110,
0b01000111,
0b01001000,
0b01001001,
0b01010000, // 50
0b01010001,
0b01010010,
0b01010011,
0b01010100,
0b01010101,
0b01010110,
0b01010111,
0b01011000,
0b01011001,
};
void main()
{
setup_comparator(NC_NC_NC_NC);
setup_adc(ADC_CLOCK_DIV_16);
setup_adc_ports(sAN0|sAN1|sAN2|sAN3);
while(1)
{
set_adc_channel(0);
for(i=0; i<15; i++)
{
Sensor_PIN_A0 = read_adc();
if( Sensor_PIN_A0 != Sensor_PIN_A0)
i=0;
}
set_adc_channel(1);
for(i=0; i<15; i++)
{
Potentiometer_PIN_A1 = read_adc();
if(Potentiometer_PIN_A1 != Potentiometer_PIN_A1)
i=0;
}
set_adc_channel(2);
for(i=0; i<15; i++)
{
Sensor_PIN_A2 = read_adc();
if(Sensor_PIN_A2 != Sensor_PIN_A2)
i=0;
}
set_adc_channel(3);
for(i=0; i<15; i++)
{
Potentiometer_PIN_A3 = read_adc();
if (Potentiometer_PIN_A3 != Potentiometer_PIN_A3)
i=0;
}
delay_ms(1);
if(input(PIN_b7) == 0)
Output = (Sensor_PIN_A0 - 559)/2;
output_c(FinalFormOfThePORTCOutput[Output]);
delay_ms(1);
if(input(PIN_B6) == 0)
Output = (Potentiometer_PIN_A1 - 559)/2;
output_c(FinalFormOfThePORTCOutput[Output]);
delay_ms(1);
if(input(PIN_B5) == 0)
Output = (Sensor_PIN_A2 - 559)/2;
output_c(FinalFormOfThePORTCOutput[Output]);
delay_ms(1);
if(input(PIN_B4) == 0)
Output = (Potentiometer_PIN_A3 - 559)/2;
output_c(FinalFormOfThePORTCOutput[Output]);
delay_ms(1000);
}
}
|
_________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Dec 25, 2016 10:33 am |
|
|
I don't see any RMW issues in your code. On PortA, you are doing analog
reads only. No writes. On PortB, you are doing digital reads only, with
no writes. On PortC, you are writing the entire port at once and not
ever reading from it. |
|
![](templates/subSilver/images/spacer.gif) |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Sun Dec 25, 2016 12:14 pm |
|
|
Thanks for the confirmation but can you tell me if there are read and write
operations on the same PORT, what are the options and how to avoid problems?
1. If you perform the same operations on the same ports, there is one whole register for PORT_B, PORT_C, PORT_A and so on and there can be no read write modify issues?
2. RWM issues are applied when when you perform different operations on 1 register and can lead to reading the ports status from the exit instead of the register.
-How much time does it take normally for the PIC to change the output levels and if necessary is 1mS delay enough to avoid problems?
-Are there any other things that can avoid or cause RWM issues?
-Is there an inside capacitor or some capacitance on the pins and buses(cables) and how much time is it necessary to avoid that any problem?
-How much time is it necessary in order to avoid all RWM issues when using funcions like input, output_high(); ? _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Sun Dec 25, 2016 12:18 pm |
|
|
OK , maybe I'm not looking at this correctly but.....
if( Sensor_PIN_A0 != Sensor_PIN_A0)
WHAT is the purpose of this ?
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Sun Dec 25, 2016 12:23 pm |
|
|
As far as I can remember in C you can do this:
X= X +B;
That means that the old value of X is summed with B and we get the new value of X.
Also it should be possible to compare the old value of X with the new value of X and if they are different reduce i to 0;
if(X != X)
i=0;
Do you think it is not accurate? _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Sun Dec 25, 2016 1:12 pm |
|
|
44: if(x!=x) y=0;
0246 5030 MOVF 0x30, W, ACCESS
0248 5C30 SUBWF 0x30, W, ACCESS
024A A4D8 BTFSS 0xfd8, 0x2, ACCESS
024C 6A31 CLRF 0x31, ACCESS
This is the code I get....
The if statement reads as follows..
IF ( x does not equal x ) THEN y becomes 1;
There is ONLY one memory location associated to 'x', 0x30.
There isn't a 'last value of x' temporary location...
The machine code 246, 248 says
1) move the contents of file F( RAM location 0x30) into W ( the Working register)
2) subtract the contents of the file F from the Working register
based on the outcome, either jump or set Y to 1.
Now I am interested in that the compiler didn't 'see' that X!=X can never be true and so just do a NOP.
Maybe I'm reading this all wrong as I haven't had any turkey yet today ?? |
|
![](templates/subSilver/images/spacer.gif) |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Sun Dec 25, 2016 2:36 pm |
|
|
temtronic wrote: | 44: if(x!=x) y=0;
0246 5030 MOVF 0x30, W, ACCESS
0248 5C30 SUBWF 0x30, W, ACCESS
024A A4D8 BTFSS 0xfd8, 0x2, ACCESS
024C 6A31 CLRF 0x31, ACCESS
This is the code I get....
The if statement reads as follows..
IF ( x does not equal x ) THEN y becomes 1;
There is ONLY one memory location associated to 'x', 0x30.
There isn't a 'last value of x' temporary location...
The machine code 246, 248 says
1) move the contents of file F( RAM location 0x30) into W ( the Working register)
2) subtract the contents of the file F from the Working register
based on the outcome, either jump or set Y to 1.
Now I am interested in that the compiler didn't 'see' that X!=X can never be true and so just do a NOP.
Maybe I'm reading this all wrong as I haven't had any turkey yet today ?? |
I can not confirm or deny! Do you have any suggestion on how to make the debouncing for the ADC if it is even necessary?
The new value has to be compared with the old value and if there is a difference do nothing. The idea is to avoid sudden spikes of the ADC pin and random capacitances.
For a digital I/O pin I know it is like this:
Code: |
for (db_count=0; db_count<15; db_count++)
{
delay_ms(1); //sample every 1 ms
if (input(GP3)==0) //if button down (GP3 low)
db_count=0; //restart count
}
|
I think that here a filter will really apply. The LM335 sensor is directly connected to the PIN, without a capacitor or anything else to filter the voltage, therefore there will be some random spikes from radio frequencies, wi-fi and so on. _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Mon Dec 26, 2016 2:41 am |
|
|
As a comment, The 'point' about RMW, is if the voltage on the pin hasn't actually got to the level it is meant to be.
Now the 'classic' is to do with the way the PIC works internally. If you perform a write immediately followed by a read on the same port. The actual 'write' takes place as the last internal clock cycle of the first instruction. The 'read' then occurs at the start of the second clock cycle of the next instruction (each instruction is four clocks).
Now if you have a pin driving into say first an 'overload' (so when set to '1' it only actually pulls up to perhaps 2v - perhaps feeding an LED without a current limit resistor), then you will permanently get RMW problems. On 'capacitance' though, at normal levels of a few hundred pF max, then even 1uSec of delay will be enough for the signal to get to the desired level. Anything involving mSec, would imply that you were massively overloading the pin.
Avoiding it. First, maintain an internal variable storing what you want on the register, and update this, then write this to the port. On the PIC18, this is why the output 'latch' is available separately to the actual 'port'.
Anyway the problem was actually nothing to do with RMW.
I'd stand firmly by the suggestion in the thread PCM_programmer pointed to, of the Olympic average. However pay very specific attention to the comment about 'know your noise'. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Mon Dec 26, 2016 6:14 am |
|
|
Mr. T's last paragraph is critical to implementing a stable project.
The Olympic averaging code is great for temperature sensors ! It's small, fast, code that does exactly what you need.
You also should read the LM335 data sheet, look at 'applications' ,etc.
If the sensors are a long distance from the PIC, I urge you to add a 'rail to rail' OPamp AT THE SENSOR location. This 'unity buffer (gain of 1)' will then drive the temp signal down the wire to the PIC. The ones I use have a double T- filter added. You can easily have 25 meters of telephone 'quad' wire as hookup and still get accurate results.
At the very, very least add a .68mfd cap to the ADC input pins to filter out some noise.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Mon Dec 26, 2016 12:18 pm |
|
|
Thanks!
Now I actually understand how the instructions go. That means 4MHz internal clock is 250nS for 1 instruction by 4MHz, so for 1MHz we will have 4*250nS=1uS. Meaning 4 instructions will be carried for 1uS with 3% accuracy from the internal oscilator?
Is it that 1 instruction is carried for 4 cycles or that the instruction clock is reduced by 4? I am guessing that the REGISTER is just connected to the internal hardware and depending on the combination something is started?
I know the processor should be as close as possible to the sensor. I was reading the datasheet :D.
I also know about shadow registers but I needed to use only one pin without a shadow register.
One repeater is enough for 25 meters?
Iin = Iout = Uin/R1 ?
That means 3V/R1, so I get 3V/10 Ohms = 300mA
300mA * 3V = 900mW for the resistor
Is this really enough?
Otherwise I will need 2 * 5Watt resistors, even 3.
Olympic average-
http://www.daycounter.com/LabBook/Moving-Average.phtml
So basically we sum toghether all 10 samples, if there is a sample greater than the others or smaller it is removed. Meaning the maximum positive spike and maximum negative spikes are removed and we average the rest?
We need to remove only 2 samples because it is good to divide by 8.
If we want to account for more that 2 spikes we should increase the samples to 12?
Why 68mF should it not be 100nF in paralel with 100pF?
I guess I should account for different noises and their frequency in order to know my noise, because my methods might not be good enough and like this I can spare methods? _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 26, 2016 12:36 pm |
|
|
Quote: | That means 4MHz internal clock is 250nS for 1 instruction by 4MHz, |
No. At 4 MHz, 1 instruction cycle is 1 usec. In most cases, you get one
instruction per microsecond. (Some instructions take two instruction
cycles, such as any instruction that jumps to a new address).
The rule is, divide the PIC's clock by 4 to get the instruction cycle clock.
If the PIC is running at 4 MHz, the instruction clock is 1 MHz. |
|
![](templates/subSilver/images/spacer.gif) |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Mon Dec 26, 2016 12:47 pm |
|
|
PCM programmer wrote: | Quote: | That means 4MHz internal clock is 250nS for 1 instruction by 4MHz, |
No. At 4 MHz, 1 instruction cycle is 1 usec. In most cases, you get one
instruction per microsecond. (Some instructions take two instruction
cycles, such as any instruction that jumps to a new address).
The rule is, divide the PIC's clock by 4 to get the instruction cycle clock.
If the PIC is running at 4 MHz, the instruction clock is 1 MHz. |
So most instructions are carried for 1 cycle of 1uS because of the optimised 14bit harvard architecture like it is said in the datasheet? Then I have to account for how long will it take the PIC to rise the output levels and see is 1 instruction enough or not. If it is not like with the newer and faster PICs I need a delay cycle. Thanks I will see what will happen. _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|