Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Idle Air Control Valve Control Related Problem

Status
Not open for further replies.

Okada

Banned
Joined
Jun 16, 2016
Messages
1,159
Helped
129
Reputation
252
Reaction score
129
Trophy points
63
Activity points
0
My project is Idle Air Control Valve Control.

I have to feedbacks that is engine temperature and cts voltage. Engine temperature varies from 0 to 40 degree and cts voltage varies from 0 to 3.5V

I need to map these values to valve angle that is stepper motor angle. stepper motor step angle is 15 degrees. I need max angle 45 degrees that is for 0 degree C and cts voltage 3.5V. For cts voltage 0 and temperature = 40 degrees I need stepper angle 15 degrees.

So, valve should operate between 15 and 45 degree so total angle of rotation needed is 30 degree.

problem is how to control one value that is stepper rotation angle based on two values namely cts voltage and temperature ?

Should I use if...else if() conditions like

Code:
if(((engine_temperature >= 0.0) && (engine temperature < 40/3)) && ((cts_voltage >= 2.33)) {
     stepper_angle = 15.0;
}
else if(((engine_temperature >= 40/3) && (engine temperature < ((40/3) * 2))) && ((cts_voltage >= 1.67) && (cts_voltage < 2.33)) {
     stepper_angle = 30.0;
}
else if(((engine_temperature >= ((40/3) * 2)) && ((cts_voltage >= 0) && (cts_voltage < 1.67)) {
     stepper_angle = 45.0;
}


Edit:

Here is the latest code


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
if(  (  (engine_temperature >= 0.0) && (engine_temperature < (ENGINE_WARM_TEMPERATURE / 3.0))) &&
               (  (cts_voltage >= (CTS_V_HIGH / 3.0)) )  ) {
               stepper_angle = 15.0;
          }
          else if(  (  (engine_temperature >= ((ENGINE_WARM_TEMPERATURE / 3.0) * 2.0)) && (engine_temperature < (ENGINE_WARM_TEMPERATURE / 3.0))  ) &&
                    (  (cts_voltage >= ((CTS_V_HIGH / 3.0) * 2.0)) && (cts_voltage < (CTS_V_HIGH / 3.0))  )  ) {
               stepper_angle = 30.0;
          }
          else if(  (engine_temperature >= (ENGINE_WARM_TEMPERATURE)) &&
                    (  (cts_voltage >= 0) && (cts_voltage < (CTS_V_HIGH / 3.0))  )  ) {
               stepper_angle = 45.0;
          }

 
Last edited:

If this is just a "project" where you have to write C code
I don't have much help for you.

In automotive PCMs with which I'm familiar, IAC position
is set by a few different mechanisms. The plunger goes
through multiple stepper rotations (counts = rotation / N)
and may move to
1) close the idle RPM control loop to desired value
2) deliver a predicted airflow that matches a desired air
mass calculation

In both cases the action is driven by 2D external data
tables, never hard coded. Always with an interpolation
function between cell values based on the index position
relative to table boundaries (thus significant data
reduction, with tolerable accuracy).

An IAC valve would never (in my experience) be bang-bang,
15 or 45 degrees. It would traverse the continuum between
based on either algorithmic or tabular figuring.

Maybe if you look at the endpoint conditions given, you
can infer a transfer function for IAC_angle(eng_temp,cts_v)

Now I would take "cts" to be "coolant temperature sensor"
which generally is taken to be engine temperature. So
what's with the two variables, when they are the same
thing basically?
 
  • Like
Reactions: Okada

    Okada

    Points: 2
    Helpful Answer Positive Rating
If the used valve angle is only 30 degree, you are using the wrong stepper motor. 30 degree sounds more like a flapper valve, I've never seen a needle valve with such a low operating angle.

Or is it just a homework/lab experiment scenario without much relation to real engineering?
 
  • Like
Reactions: Okada

    Okada

    Points: 2
    Helpful Answer Positive Rating
@FvM

I have never worked with automotive electronics. This is a request by a student regarding his college project. The only data provided to me is this one.

**broken link removed**

The student doesn't know how what angle the stepper has to rotate to open or close the IAC Valve.

I am only trying to help a student. He said motor is bi-polar stepper motor. He has to show Proteus Simulation.

1. If I have to make the simulation similar to read world one then what should be the angle for opening or closing the valve ?

2. How to make a function which can control the angle of opening or closing the valve based on angle valve provided to it assuming angle is integer type ?

3. Or should I use microstepping ?




Edit:

I referred this.

https://ww1.microchip.com/downloads/en/AppNotes/00822a.pdf

See page no. 17. Can I Implement that Microstepping using PIC16F877A and L293D ?
 
Last edited:

I have no experience with Bi-Polar Stepper Motor Microstepping and hence have used normal method of giving step pulses. This is the latest code. It is not working. Motor is not running. What is the problem ?

I have used this function.

https://www.jetmore.org/john/blog/2011/09/arduinos-map-function-and-numeric-distribution/


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
#define ADC_0_REF 5.0
#define ADC_1_REF 500.0
 
#define ADC_RESOLUTION 1023.0
 
#define ENGINE_COLD_START_TEMPERATURE  0.2
#define ENGINE_WARM_TEMPERATURE       40.0
 
#define CTS_V_LOW  0.2
#define CTS_V_HIGH 3.9
 
#define ENGINE_COLD 1
#define ENGINE_WARM 0
 
#define IACV_PORT PORTB
 
#define STEP_SIZE 15.0
 
#define NO_ROTATION 0
#define CCW         1
#define CW          2
 
#define MIN_ANGLE 45.0
#define MAX_ANGLE 720.0
 
const code char txt1[] = "T: ";
const code char txt2[] = "V: ";
const code char txt3[] = "             ";
 
char txt[23];
const char character[] = {6,9,9,6,0,0,0,0};
unsigned char stepper_motor_sequence[4] = {0x80, 0x20, 0x40, 0x10};
unsigned char engine_state_counter = 0;
char i = 0, j = 0;
unsigned char my_flags = 0;
long int raw_adc_value[2] = {0, 0};
long int previous_raw_adc_value[2] = {200, 10};
double engine_temperature = 0.0;
double cts_voltage = 0.0;
double angle_based_on_engine_temperature = 0.0;
double angle_based_on_cts_voltage = 0.0;
char stepper_angle = 0;
char previous_stepper_angle = 0;
unsigned char no_of_steps_required = 0;
char direction_of_steps = 0;
 
char *CopyConst2Ram(char *dest, const code char *src){
    char *d;
 
    d = dest;
 
    for(;*dest++ = *src++;);
 
    return d;
}
 
void CustomChar(char pos_row, char pos_char) {
    char i;
    
    Lcd_Cmd(64);
    
    for (i = 0; i <= 7; i++) Lcd_Chr_CP(character[i]);
 
    Lcd_Chr(pos_row, pos_char, 0);
}
 
double map(double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
unsigned char Get_No_Of_Steps_Required(double angle) {
    return (unsigned char)((unsigned int)angle / STEP_SIZE);
}
 
char Get_Required_Direction(double angle, double previous_angle) {
    if(angle < previous_angle) {
        return 1;
    }
    else if(angle > previous_angle) {
        return 2;
    }
    if(angle == previous_angle) {
        return 0;
    }
}
 
void main() {
 
    CMCON = 0x07;
    
    ADCON0 = 0x40;
    ADCON1 = 0x84;
    
    TRISA = 0x03;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(200);
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt, txt1));
    LCD_Out(2,1,CopyConst2Ram(txt, txt2));
 
    while(1) {
 
 
          raw_adc_value[0] = (long int)ADC_Read(0);
          Delay_us(20);
          raw_adc_value[1] = (long int)ADC_Read(1);
          Delay_us(20);
          
          if((previous_raw_adc_value[0] != raw_adc_value[0]) || (previous_raw_adc_value[1] != raw_adc_value[1])) {
              cts_voltage = (double)raw_adc_value[0] * ADC_0_REF / ADC_RESOLUTION;
              engine_temperature = (double)raw_adc_value[1] * ADC_1_REF / ADC_RESOLUTION;
 
              LCD_Out(2,4,CopyConst2Ram(txt, txt3));
              FloatToStr(cts_voltage, txt);
              strcat(txt, "V");
              LCD_Out(2,4,txt);
              
              LCD_Out(1,4,CopyConst2Ram(txt, txt3));
              FloatToStr_FixLen(engine_temperature, txt, 5);
              LCD_Out(1,4,txt);
              CustomChar(1,9);
              LCD_Out(1,10,"C");
 
              angle_based_on_engine_temperature = map(engine_temperature, ENGINE_COLD_START_TEMPERATURE, 
              ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
              angle_based_on_cts_voltage = map(cts_voltage, CTS_V_LOW, CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);
 
              if(angle_based_on_engine_temperature == angle_based_on_cts_voltage) {
                  stepper_angle = angle_based_on_engine_temperature;
              }
              
              if(previous_stepper_angle != stepper_angle) {
                  no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle);
                  direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);
                  
                  switch(direction_of_steps) {
                        case 0:
                               break;
                        case 1:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j--];
                                   Delay_ms(100);
                                   j = abs(j);
                                   j = j % 4;
                               }
                               break;
                        case 2:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j++];
                                   Delay_ms(100);
                                   j = j % 4;
                               }
                               break;
                  };
 
                  
                  previous_stepper_angle = stepper_angle;
              }
              
              IntToStr((int)stepper_angle, txt);
              Ltrim(txt);
              LCD_Out(1,15,txt);
              
              previous_raw_adc_value[0] = raw_adc_value[0];
              previous_raw_adc_value[1] = raw_adc_value[1];
          }
    }
}




Edit:

This is the new code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
switch(direction_of_steps) {
                        case 0:
                               break;
                        case 1:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j--];
                                   Delay_ms(100);
                                   j = j - 2;
                                   j = abs(j);
                                   j = j % 4;
                               }
                               break;
                        case 2:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j++];
                                   Delay_ms(100);
                                   j = j % 4;
                               }
                               break;
                  };



- - - Updated - - -

Edit 2:

Fixed one bug.

Code:
for(i = 0; i < no_of_steps_required; i++) {
         j = j + 3;
         j = j % 4;
     }
 

Attachments

  • IAC Valve Control.rar
    118.5 KB · Views: 70
Last edited:

According to datasheet, the full valve travel is about 240 steps with the 15°/step motor. That's probably sufficient resolution without micro stepping, in case you could refer to half steps to increase the resolution.

The actor has no position feedback, expect to zero the position initially (after turning on the ignition switch) by closing it fully and keep track of the actual positions after that.
 
  • Like
Reactions: Okada

    Okada

    Points: 2
    Helpful Answer Positive Rating
Ok FvM

This is the latest code but still the stepper motor is not operating. It is failing here.

Code:
if(angle_based_on_engine_temperature == angle_based_on_cts_voltage) {
                  stepper_angle = angle_based_on_engine_temperature;
                  
                  IntToStr((int)stepper_angle, txt);
                  Ltrim(txt);
                  LCD_Out(1,15,txt);
              }

This is the full code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
#define ADC_0_REF 5.0
#define ADC_1_REF 500.0
 
#define ADC_RESOLUTION 1023.0
 
/*
#define ENGINE_COLD_START_TEMPERATURE  0.0
#define ENGINE_WARM_TEMPERATURE       45.0
*/
 
#define ENGINE_COLD_START_TEMPERATURE  0.0
#define ENGINE_WARM_TEMPERATURE       82.0
 
/*
#define CTS_V_LOW  0.0
#define CTS_V_HIGH 3.9
*/
 
#define CTS_V_LOW    0.0
#define CTS_V_HIGH 798.0
 
#define IACV_PORT PORTB
 
#define STEP_SIZE 15.0
 
#define NO_ROTATION 0
#define CCW         1
#define CW          2
 
#define MIN_ANGLE   45.0
#define MAX_ANGLE 3600.0           // 15 degree / step, 240 steps
 
const code char txt1[] = "T: ";
const code char txt2[] = "V: ";
const code char txt3[] = "             ";
 
char txt[23];
const char character[] = {6,9,9,6,0,0,0,0};
unsigned char stepper_motor_sequence[4] = {0x80, 0x20, 0x40, 0x10};
unsigned char engine_state_counter = 0;
char i = 0, j = 0;
unsigned char my_flags = 0;
long int raw_adc_value[2] = {0, 0};
long int previous_raw_adc_value[2] = {2048, 2048};
double engine_temperature = 0.0;
double cts_voltage = 0.0;
int angle_based_on_engine_temperature = 0.0;
int angle_based_on_cts_voltage = 0.0;
char stepper_angle = 0;
char previous_stepper_angle = 0.0;
unsigned char no_of_steps_required = 0;
char direction_of_steps = 0;
 
char *CopyConst2Ram(char *dest, const code char *src){
    char *d;
 
    d = dest;
 
    for(;*dest++ = *src++;);
 
    return d;
}
 
void CustomChar(char pos_row, char pos_char) {
    char i;
    
    Lcd_Cmd(64);
    
    for (i = 0; i <= 7; i++) Lcd_Chr_CP(character[i]);
 
    Lcd_Chr(pos_row, pos_char, 0);
}
 
double map(double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
unsigned char Get_No_Of_Steps_Required(double angle) {
    return (unsigned char)((unsigned int)angle / STEP_SIZE);
}
 
char Get_Required_Direction(double angle, double previous_angle) {
    if(angle < previous_angle) {
        return 1;
    }
    else if(angle > previous_angle) {
        return 2;
    }
    if(angle == previous_angle) {
        return 0;
    }
}
 
void main() {
 
    CMCON = 0x07;
    
    ADCON0 = 0x40;
    ADCON1 = 0x84;
    
    TRISA = 0x03;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(200);
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt, txt1));
    LCD_Out(2,1,CopyConst2Ram(txt, txt2));
 
    while(1) {
 
 
          raw_adc_value[0] = (long int)ADC_Read(0);
          Delay_us(20);
          raw_adc_value[1] = (long int)ADC_Read(1);
          Delay_us(20);
          
          if((previous_raw_adc_value[0] != raw_adc_value[0]) || (previous_raw_adc_value[1] != raw_adc_value[1])) {
              cts_voltage = (double)raw_adc_value[0] * ADC_0_REF / ADC_RESOLUTION;
              engine_temperature = (double)raw_adc_value[1] * ADC_1_REF / ADC_RESOLUTION;
 
              LCD_Out(2,4,CopyConst2Ram(txt, txt3));
              FloatToStr(cts_voltage, txt);
              strcat(txt, "V");
              LCD_Out(2,4,txt);
              
              LCD_Out(1,4,CopyConst2Ram(txt, txt3));
              FloatToStr_FixLen(engine_temperature, txt, 5);
              LCD_Out(1,4,txt);
              CustomChar(1,9);
              LCD_Out(1,10,"C");
 
              /*
              angle_based_on_engine_temperature = map(engine_temperature, ENGINE_COLD_START_TEMPERATURE, 
                                                      ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
              angle_based_on_cts_voltage = map(cts_voltage, CTS_V_LOW, CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);
              */
              
              if(raw_adc_value[1] <= ENGINE_WARM_TEMPERATURE) {
                  angle_based_on_engine_temperature = (int)map(raw_adc_value[1], ENGINE_COLD_START_TEMPERATURE,
                                                          ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
                                                      
              }
              
              if(raw_adc_value[1] <= CTS_V_HIGH) {
                  angle_based_on_cts_voltage = (int)map(raw_adc_value[0], CTS_V_LOW,
                                                          CTS_V_HIGH, MAX_ANGLE, MIN_ANGLE);
 
              }
              
              if(angle_based_on_engine_temperature == angle_based_on_cts_voltage) {
                  stepper_angle = angle_based_on_engine_temperature;
                  
                  IntToStr((int)stepper_angle, txt);
                  Ltrim(txt);
                  LCD_Out(1,15,txt);
              }
              
              IntToStr((int)stepper_angle, txt);
              Ltrim(txt);
              LCD_Out(1,15,txt);
 
              if(previous_stepper_angle != stepper_angle) {
                  no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle);
                  direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);
                  
                  switch(direction_of_steps) {
                        case 0:
                               break;
                        case 1:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j--];
                                   Delay_ms(100);
                                   j = j + 4;
                                   j = j % 4;
                               }
                               break;
                        case 2:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j++];
                                   Delay_ms(100);
                                   j = j % 4;
                               }
                               break;
                  };
 
                  
                  previous_stepper_angle = stepper_angle;
              }
 
              previous_raw_adc_value[0] = raw_adc_value[0];
              previous_raw_adc_value[1] = raw_adc_value[1];
          }
    }
}




Edit 2:

Stepper motor started working but the angle shown is not equal to angle rotated. If it shows 16 degree on LCD then stepper rotates 15 degrees.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
#define ADC_0_REF 5.0
#define ADC_1_REF 500.0
 
#define ADC_RESOLUTION 1023.0
 
#define ENGINE_COLD_START_TEMPERATURE  0.0  //0 degree C
#define ENGINE_WARM_TEMPERATURE       82.0  //40 degree C
 
#define CTS_V_LOW    0.0  //0V
#define CTS_V_HIGH 798.0  //3.9V
 
#define IACV_PORT PORTB
 
#define STEP_SIZE 15.0
 
#define NO_ROTATION 0
#define CCW         1
#define CW          2
 
#define MIN_ANGLE   45.0
#define MAX_ANGLE 3600.0           // 15 degree / step, 240 steps
 
const code char txt1[] = "T: ";
const code char txt2[] = "V: ";
const code char txt3[] = "             ";
 
char txt[23];
const char character[] = {6,9,9,6,0,0,0,0};
unsigned char stepper_motor_sequence[4] = {0x80, 0x20, 0x40, 0x10};
unsigned char engine_state_counter = 0;
char i = 0, j = 0;
unsigned char my_flags = 0;
long int raw_adc_value[2] = {0, 0};
long int previous_raw_adc_value[2] = {2048, 2048};
double engine_temperature = 0.0;
double cts_voltage = 0.0;
int angle_based_on_engine_temperature = 0;
int angle_based_on_cts_voltage = 0;
char stepper_angle = 0;
char previous_stepper_angle = 0.0;
unsigned char no_of_steps_required = 0;
char direction_of_steps = 0;
 
char *CopyConst2Ram(char *dest, const code char *src){
    char *d;
 
    d = dest;
 
    for(;*dest++ = *src++;);
 
    return d;
}
 
void CustomChar(char pos_row, char pos_char) {
    char i;
    
    Lcd_Cmd(64);
    
    for (i = 0; i <= 7; i++) Lcd_Chr_CP(character[i]);
 
    Lcd_Chr(pos_row, pos_char, 0);
}
 
double map(double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
unsigned char Get_No_Of_Steps_Required(double angle) {
    return (unsigned char)((unsigned int)angle / STEP_SIZE);
}
 
char Get_Required_Direction(double angle, double previous_angle) {
    if(angle < previous_angle) {
        return 1;
    }
    else if(angle > previous_angle) {
        return 2;
    }
    if(angle == previous_angle) {
        return 0;
    }
}
 
void main() {
 
    CMCON = 0x07;
    
    ADCON0 = 0x40;
    ADCON1 = 0x84;
    
    TRISA = 0x03;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(200);
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt, txt1));
    LCD_Out(2,1,CopyConst2Ram(txt, txt2));
 
    while(1) {
 
          raw_adc_value[0] = (long int)ADC_Read(0);
          Delay_us(20);
          raw_adc_value[1] = (long int)ADC_Read(1);
          Delay_us(20);
 
          if((previous_raw_adc_value[0] != raw_adc_value[0]) || (previous_raw_adc_value[1] != raw_adc_value[1])) {
              cts_voltage = (double)raw_adc_value[0] * ADC_0_REF / ADC_RESOLUTION;
              engine_temperature = (double)raw_adc_value[1] * ADC_1_REF / ADC_RESOLUTION;
 
              LCD_Out(2,4,CopyConst2Ram(txt, txt3));
              FloatToStr(cts_voltage, txt);
              strcat(txt, "V");
              LCD_Out(2,4,txt);
              
              LCD_Out(1,4,CopyConst2Ram(txt, txt3));
              FloatToStr_FixLen(engine_temperature, txt, 5);
              LCD_Out(1,4,txt);
              CustomChar(1,9);
              LCD_Out(1,10,"C");
 
              if(raw_adc_value[1] <= ENGINE_WARM_TEMPERATURE) {
                  angle_based_on_engine_temperature = (int)map(raw_adc_value[1], ENGINE_COLD_START_TEMPERATURE,
                                                          ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
                                                      
              }
              
              if(raw_adc_value[0] <= CTS_V_HIGH) {
                  angle_based_on_cts_voltage = (int)map(raw_adc_value[0], CTS_V_LOW,
                                                          CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);
 
              }
              
              if(angle_based_on_engine_temperature == angle_based_on_cts_voltage) {
                  stepper_angle = angle_based_on_engine_temperature;
              }
              
              IntToStr((int)stepper_angle, txt);
              Ltrim(txt);
              LCD_Out(1,15,txt);
 
              if(previous_stepper_angle != stepper_angle) {
                  no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle);
                  direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);
                  
                  switch(direction_of_steps) {
                        case 0:
                               break;
                        case 1:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j--];
                                   Delay_ms(100);
                                   j = j + 4;
                                   j = j % 4;
                               }
                               break;
                        case 2:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j++];
                                   Delay_ms(100);
                                   j = j % 4;
                               }
                               break;
                  };
 
                  
                  previous_stepper_angle = stepper_angle;
              }
 
              previous_raw_adc_value[0] = raw_adc_value[0];
              previous_raw_adc_value[1] = raw_adc_value[1];
          }
    }
}



In the Edit 2 code the changes made aare

Code:
if(raw_adc_value[0] <= CTS_V_HIGH) {
                  angle_based_on_cts_voltage = (int)map(raw_adc_value[0], CTS_V_LOW,
                                                          CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);

              }
 
Last edited:

@Experts

It is not working. What is the problem ?

I have fixed

Code:
Get_No_Of_Steps()

function.

Initially the stepper rotates but after that if I vary CTS Voltage and Engine Temperature then stepper doesn't rotate.

This is the latest project. Only consider Revision G file.

Here is the code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
#define ADC_0_REF 5.0
#define ADC_1_REF 500.0
 
#define ADC_RESOLUTION 1023.0
 
#define ENGINE_COLD_START_TEMPERATURE  0.0  //0 degree C
#define ENGINE_WARM_TEMPERATURE       82.0  //40 degree C
 
#define CTS_V_LOW    0.0  //0V
#define CTS_V_HIGH 798.0  //3.9V
 
#define IACV_PORT PORTB
 
#define STEP_SIZE 15.0
 
#define NO_ROTATION 0
#define CCW         1
#define CW          2
 
#define MIN_ANGLE   15.0
#define MAX_ANGLE 270.0           // 15 degree / step, 240 steps
 
#define ENGINE_TEMPERATURE_STEP_SIZE 1.0
#define CTS_VOLTAGE_STEP_SIZE        0.1
 
#define ENGINE_TEMP_LOW   0.0
#define ENGINE_TEMP_HIGH 40.0
 
#define CTS_VOLTAGE_LOW  0.0
#define CTS_VOLTAGE_HIGH 3.9
 
const code char txt1[] = "T: ";
const code char txt2[] = "V: ";
const code char txt3[] = "             ";
 
const code char txt4[] = "CTS_V , STEPPER ANGLE , NO. OF STEPS\r\n";
const code char txt5[] = "T , STEPPER ANGLE , NO. OF STEPS\r\n";
const code char txt6[] = " , ";
 
char txt[43];
const char character[] = {6,9,9,6,0,0,0,0};
unsigned char stepper_motor_sequence[4] = {0x80, 0x20, 0x40, 0x10};
unsigned char engine_state_counter = 0;
char i = 0, j = 0;
unsigned char my_flags = 0;
long int raw_adc_value[2] = {0, 0};
long int previous_raw_adc_value[2] = {2048, 2048};
double engine_temperature = 0.0;
double cts_voltage = 0.0;
int angle_based_on_engine_temperature = 0;
int angle_based_on_cts_voltage = 0;
int stepper_angle = 0;
int previous_stepper_angle = 0.0;
unsigned char no_of_steps_required = 0;
char direction_of_steps = 0;
 
double k = 0.0, q = 0.0;
int h = 0, m = 0, n = 0, t = 0;
 
char *CopyConst2Ram(char *dest, const code char *src){
    char *d;
 
    d = dest;
 
    for(;*dest++ = *src++;);
 
    return d;
}
 
void CustomChar(char pos_row, char pos_char) {
    char i;
    
    Lcd_Cmd(64);
    
    for (i = 0; i <= 7; i++) Lcd_Chr_CP(character[i]);
 
    Lcd_Chr(pos_row, pos_char, 0);
}
 
double map(double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
unsigned char Get_No_Of_Steps_Required(double angle, double previous_angle) {
    if(previous_angle > angle) {
        return (unsigned char)(((unsigned int)previous_angle / STEP_SIZE) - ((unsigned int)angle / STEP_SIZE));
    }
    else if(previous_angle < angle) {
        return (unsigned char)(((unsigned int)angle / STEP_SIZE) - ((unsigned int)previous_angle / STEP_SIZE));
    }
    else if(previous_angle == angle) {
        return (unsigned char)(((unsigned int)angle / STEP_SIZE) - ((unsigned int)previous_angle / STEP_SIZE));
    }
    
    //return (unsigned char)((unsigned int)angle / STEP_SIZE);
}
 
char Get_Required_Direction(double angle, double previous_angle) {
    if(angle < previous_angle) {
        return 1;
    }
    else if(angle > previous_angle) {
        return 2;
    }
    if(angle == previous_angle) {
        return 0;
    }
}
 
void main() {
 
    //no_of_steps_required = Get_No_Of_Steps_Required(45.0, 240.0);
    
    CMCON = 0x07;
    
    ADCON0 = 0x40;
    ADCON1 = 0x84;
    
    TRISA = 0x03;
    TRISB = 0x00;
    TRISC = 0x80;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(200);
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt, txt1));
    LCD_Out(2,1,CopyConst2Ram(txt, txt2));
    
    UART1_Init(9600);
    Delay_ms(100);
    
    UART1_Write_Text(CopyConst2Ram(txt, txt4));
    
    for(k = CTS_VOLTAGE_LOW ; k <= CTS_VOLTAGE_HIGH; k = k + CTS_VOLTAGE_STEP_SIZE) {
        h = (((MAX_ANGLE - MIN_ANGLE) / (CTS_VOLTAGE_HIGH - CTS_VOLTAGE_LOW))*k + MIN_ANGLE);   //911.538*k = 45.0
        FloatToStr(k, txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt6));
        IntToStr(h, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt6));
        n = h/STEP_SIZE;
        IntToStr(n, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text("\r\n");
    }
    
    UART1_Write_Text("\r\n");
    UART1_Write_Text(CopyConst2Ram(txt, txt5));
    
    for(t = ENGINE_TEMP_HIGH; t >= ENGINE_TEMP_LOW; t = t - 1) {
        m = floor(((MAX_ANGLE - MIN_ANGLE) / (ENGINE_TEMP_LOW - ENGINE_TEMP_HIGH))*t + MAX_ANGLE);  //-88.8875*k = 3600
        IntToStr(t, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt6));
        IntToStr(m, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt6));
        n = m/STEP_SIZE;
        IntToStr(n, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text("\r\n");
    }
 
    while(1) {
 
          raw_adc_value[0] = (long int)ADC_Read(0);
          Delay_us(20);
          raw_adc_value[1] = (long int)ADC_Read(1);
          Delay_us(20);
 
          if((previous_raw_adc_value[0] != raw_adc_value[0]) || (previous_raw_adc_value[1] != raw_adc_value[1])) {
              cts_voltage = (double)raw_adc_value[0] * ADC_0_REF / ADC_RESOLUTION;
              engine_temperature = (double)raw_adc_value[1] * ADC_1_REF / ADC_RESOLUTION;
 
              LCD_Out(2,4,CopyConst2Ram(txt, txt3));
              FloatToStr(cts_voltage, txt);
              strcat(txt, "V");
              LCD_Out(2,4,txt);
              
              LCD_Out(1,4,CopyConst2Ram(txt, txt3));
              FloatToStr_FixLen(engine_temperature, txt, 5);
              LCD_Out(1,4,txt);
              CustomChar(1,9);
              LCD_Out(1,10,"C");
 
              if(raw_adc_value[1] <= ENGINE_WARM_TEMPERATURE) {
                  angle_based_on_engine_temperature = (int)map(raw_adc_value[1], ENGINE_COLD_START_TEMPERATURE,
                                                          ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
 
              }
 
              if(raw_adc_value[0] <= CTS_V_HIGH) {
                  angle_based_on_cts_voltage = (int)map(raw_adc_value[0], CTS_V_LOW,
                                                          CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);
 
              }
              
              if(angle_based_on_engine_temperature == angle_based_on_cts_voltage) {
                  stepper_angle = angle_based_on_engine_temperature;
              }
              
              IntToStr((int)stepper_angle, txt);
              Ltrim(txt);
              LCD_Out(1,12,txt);
 
              if(previous_stepper_angle != stepper_angle) {
                  no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle, previous_stepper_angle);
                  direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);
                  
                  switch(direction_of_steps) {
                        case 0:
                               break;
                        case 1:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j--];
                                   Delay_ms(50);
                                   j = j + 4;
                                   j = j % 4;
                               }
                               break;
                        case 2:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j++];
                                   Delay_ms(50);
                                   j = j % 4;
                               }
                               break;
                  };
 
                  
                  previous_stepper_angle = stepper_angle;
              }
 
              previous_raw_adc_value[0] = raw_adc_value[0];
              previous_raw_adc_value[1] = raw_adc_value[1];
          }
    }
}





Edit:

Discard all previous files and only consider Revision I file.

Table creation code is simplified. Now single table shows all values.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
#define ADC_0_REF 5.0
#define ADC_1_REF 500.0
 
#define ADC_RESOLUTION 1023.0
 
#define ENGINE_COLD_START_TEMPERATURE  0.0  //0 degree C
#define ENGINE_WARM_TEMPERATURE       82.0  //40 degree C
 
#define CTS_V_LOW    0.0  //0V
#define CTS_V_HIGH 798.0  //3.9V
 
#define IACV_PORT PORTB
 
#define STEP_SIZE 15.0
 
#define NO_ROTATION 0
#define CCW         1
#define CW          2
 
#define MIN_ANGLE   15.0
#define MAX_ANGLE 270.0           // 15 degree / step, 240 steps
 
#define ENGINE_TEMPERATURE_STEP_SIZE 1.0
#define CTS_VOLTAGE_STEP_SIZE        0.1
 
#define ENGINE_TEMP_LOW   0.0
#define ENGINE_TEMP_HIGH 40.0
 
#define CTS_VOLTAGE_LOW  0.0
#define CTS_VOLTAGE_HIGH 3.9
 
const code char txt1[] = "T: ";
const code char txt2[] = "V: ";
const code char txt3[] = "             ";
 
const code char txt4[] = "CTS V , ENGINE TEMPERATURE , STEPPER ANGLE , NO. OF STEPS\r\n";
const code char txt5[] = " , ";
 
char txt[63];
const char character[] = {6,9,9,6,0,0,0,0};
unsigned char stepper_motor_sequence[4] = {0x80, 0x20, 0x40, 0x10};
unsigned char engine_state_counter = 0;
char i = 0, j = 0;
unsigned char my_flags = 0;
long int raw_adc_value[2] = {0, 0};
long int previous_raw_adc_value[2] = {2048, 2048};
double engine_temperature = 0.0;
double cts_voltage = 0.0;
int angle_based_on_engine_temperature = 0;
int angle_based_on_cts_voltage = 0;
int stepper_angle = 0;
int previous_stepper_angle = 0.0;
unsigned char no_of_steps_required = 0;
char direction_of_steps = 0;
 
double k = 0.0, q = 0.0;
int h = 0, m = 0, n = 0, t = 0;
 
char *CopyConst2Ram(char *dest, const code char *src){
    char *d;
 
    d = dest;
 
    for(;*dest++ = *src++;);
 
    return d;
}
 
void CustomChar(char pos_row, char pos_char) {
    char i;
    
    Lcd_Cmd(64);
    
    for (i = 0; i <= 7; i++) Lcd_Chr_CP(character[i]);
 
    Lcd_Chr(pos_row, pos_char, 0);
}
 
double map(double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
unsigned char Get_No_Of_Steps_Required(double angle, double previous_angle) {
    if(previous_angle > angle) {
        return (unsigned char)(((unsigned int)previous_angle / STEP_SIZE) - ((unsigned int)angle / STEP_SIZE));
    }
    else if(previous_angle < angle) {
        return (unsigned char)(((unsigned int)angle / STEP_SIZE) - ((unsigned int)previous_angle / STEP_SIZE));
    }
    else if(previous_angle == angle) {
        return (unsigned char)(((unsigned int)angle / STEP_SIZE) - ((unsigned int)previous_angle / STEP_SIZE));
    }
    
    //return (unsigned char)((unsigned int)angle / STEP_SIZE);
}
 
char Get_Required_Direction(double angle, double previous_angle) {
    if(angle < previous_angle) {
        return 1;
    }
    else if(angle > previous_angle) {
        return 2;
    }
    if(angle == previous_angle) {
        return 0;
    }
}
 
void main() {
 
    //no_of_steps_required = Get_No_Of_Steps_Required(45.0, 240.0);
    
    CMCON = 0x07;
    
    ADCON0 = 0x40;
    ADCON1 = 0x84;
    
    TRISA = 0x03;
    TRISB = 0x00;
    TRISC = 0x80;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(200);
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt, txt1));
    LCD_Out(2,1,CopyConst2Ram(txt, txt2));
    
    UART1_Init(9600);
    Delay_ms(100);
    
    UART1_Write_Text(CopyConst2Ram(txt, txt4));
    
    for(k = CTS_VOLTAGE_LOW, t = ENGINE_TEMP_HIGH;  k <= CTS_VOLTAGE_HIGH, t >= ENGINE_TEMP_LOW; k = k + CTS_VOLTAGE_STEP_SIZE, t = t - 1) {
        h = (((MAX_ANGLE - MIN_ANGLE) / (CTS_VOLTAGE_HIGH - CTS_VOLTAGE_LOW))*k + MIN_ANGLE);   //911.538*k = 45.0
        FloatToStr(k, txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        m = floor(((MAX_ANGLE - MIN_ANGLE) / (ENGINE_TEMP_LOW - ENGINE_TEMP_HIGH))*t + MAX_ANGLE);  //-88.8875*k = 3600
        IntToStr(t, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        IntToStr(h, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        n = h/STEP_SIZE;
        IntToStr(n, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text("\r\n");
    }
 
    UART1_Write_Text("\r\n");
    
    while(1) {
 
          raw_adc_value[0] = (long int)ADC_Read(0);
          Delay_us(20);
          raw_adc_value[1] = (long int)ADC_Read(1);
          Delay_us(20);
 
          if((previous_raw_adc_value[0] != raw_adc_value[0]) || (previous_raw_adc_value[1] != raw_adc_value[1])) {
              cts_voltage = (double)raw_adc_value[0] * ADC_0_REF / ADC_RESOLUTION;
              engine_temperature = (double)raw_adc_value[1] * ADC_1_REF / ADC_RESOLUTION;
 
              LCD_Out(2,4,CopyConst2Ram(txt, txt3));
              FloatToStr(cts_voltage, txt);
              strcat(txt, "V");
              LCD_Out(2,4,txt);
              
              LCD_Out(1,4,CopyConst2Ram(txt, txt3));
              FloatToStr_FixLen(engine_temperature, txt, 5);
              LCD_Out(1,4,txt);
              CustomChar(1,9);
              LCD_Out(1,10,"C");
 
              if(raw_adc_value[1] <= ENGINE_WARM_TEMPERATURE) {
                  angle_based_on_engine_temperature = (int)map(raw_adc_value[1], ENGINE_COLD_START_TEMPERATURE,
                                                          ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
 
              }
 
              if(raw_adc_value[0] <= CTS_V_HIGH) {
                  angle_based_on_cts_voltage = (int)map(raw_adc_value[0], CTS_V_LOW,
                                                          CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);
 
              }
              
              if(angle_based_on_engine_temperature == angle_based_on_cts_voltage) {
                  stepper_angle = angle_based_on_engine_temperature;
              }
              
              IntToStr((int)stepper_angle, txt);
              Ltrim(txt);
              LCD_Out(1,12,txt);
 
              if(previous_stepper_angle != stepper_angle) {
                  no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle, previous_stepper_angle);
                  direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);
                  
                  switch(direction_of_steps) {
                        case 0:
                               break;
                        case 1:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j--];
                                   Delay_ms(50);
                                   j = j + 4;
                                   j = j % 4;
                               }
                               break;
                        case 2:
                               for(i = 0; i < no_of_steps_required; i++) {
                                   IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[j++];
                                   Delay_ms(50);
                                   j = j % 4;
                               }
                               break;
                  };
 
                  
                  previous_stepper_angle = stepper_angle;
              }
 
              previous_raw_adc_value[0] = raw_adc_value[0];
              previous_raw_adc_value[1] = raw_adc_value[1];
          }
    }
}

 

Attachments

  • IAC Valve Control - Revision G.rar
    363.1 KB · Views: 78
  • IAC Valve Control - Revision I.rar
    149.6 KB · Views: 70
Last edited:

This is the latest code. Still it is not working as expected that is the motor control.

This is the piece of code that controls the motor.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
switch(direction_of_steps) {
      case 0:
             break;
      case 1:       //if CCW, close valve
             stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 2;
             stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
 
             for(i = 0; i < no_of_steps_required; i++) {
                 IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index--];
                 Delay_ms(100);
                 stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 4;
                 stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
             }
             break;
      case 2:         //if CW, open valve
             stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index - 1;
             stepper_motor_sequence_lut_index = abs(stepper_motor_sequence_lut_index);
 
             for(i = 0; i < no_of_steps_required; i++) {
                 IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index++];
                 Delay_ms(100);
                 stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
             }
             break;
};





This is the full code. Also the code related to creation of data table which is before the while(1) loop is changed. I am posting full code if anybody want to have a look at it without opening the attached project file. It is assumed that motor is closed initially and when device is turned ON then based on engine temperature and cts voltage value the valve will open to the required angle. Check the last entry of the attached table (.csv file opens in excel). It is not correct. What is wrong in table creation code ?


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
#define ADC_0_REF 5.0
#define ADC_1_REF 500.0
 
#define ADC_RESOLUTION 1023.0
 
#define ENGINE_COLD_START_TEMPERATURE  0.0  //0 degree C
#define ENGINE_WARM_TEMPERATURE       82.0  //40 degree C
 
#define CTS_V_LOW    0.0  //0V
#define CTS_V_HIGH 798.0  //3.9V
 
#define IACV_PORT PORTB
 
#define STEP_SIZE 15.0
 
#define NO_ROTATION 0
#define CCW         1
#define CW          2
 
#define MIN_ANGLE   45.0
#define MAX_ANGLE 3600.0           // 15 degree / step, 240 steps, 3600 degree
 
#define ENGINE_TEMPERATURE_STEP_SIZE 1.0
#define CTS_VOLTAGE_STEP_SIZE        0.1
 
#define ENGINE_TEMP_LOW   0.0
#define ENGINE_TEMP_HIGH 40.0
 
#define CTS_VOLTAGE_LOW  0.0
#define CTS_VOLTAGE_HIGH 3.9
 
const code char txt1[] = "T: ";
const code char txt2[] = "V: ";
const code char txt3[] = "             ";
 
const code char txt4[] = "CTS V , ENGINE TEMPERATURE , STEPPER ANGLE , NO. OF STEPS\r\n";
const code char txt5[] = " , ";
const code char txt6[] = "\r\n";
 
char txt[63];
const char character[] = {6,9,9,6,0,0,0,0};
unsigned char stepper_motor_sequence[4] = {0x80, 0x20, 0x40, 0x10};
unsigned char engine_state_counter = 0;
char i = 0, j = 0;
unsigned char my_flags = 0;
long int raw_adc_value[2] = {0, 0};
long int previous_raw_adc_value[2] = {2048, 2048};
double engine_temperature = 0.0;
double cts_voltage = 0.0;
int stepper_angle_based_on_engine_temperature = 0;
int stepper_angle_based_on_cts_voltage = 0;
int stepper_angle = 0;
int previous_stepper_angle = 0.0;
unsigned char no_of_steps_required = 0;
char direction_of_steps = 0;
char stepper_motor_sequence_lut_index = 1;
 
char *CopyConst2Ram(char *dest, const code char *src){
    char *d;
 
    d = dest;
 
    for(;*dest++ = *src++;);
 
    return d;
}
 
void CustomChar(char pos_row, char pos_char) {
    char i;
    
    Lcd_Cmd(64);
    
    for (i = 0; i <= 7; i++) Lcd_Chr_CP(character[i]);
 
    Lcd_Chr(pos_row, pos_char, 0);
}
 
double map(double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
unsigned char Get_No_Of_Steps_Required(int angle, int previous_angle) {
    if(angle < previous_angle) {
        return (unsigned char)((previous_angle - angle) / STEP_SIZE);
    }
    else if(angle > previous_angle) {
        return (unsigned char)((angle - previous_angle) / STEP_SIZE);
    }
    else if(angle == previous_angle) {
        return 0;
    }
}
 
char Get_Required_Direction(int angle, int previous_angle) {
    if(angle < previous_angle) {
        return 1;
    }
    else if(angle > previous_angle) {
        return 2;
    }
    if(angle == previous_angle) {
        return 0;
    }
}
 
void main() {
    
    CMCON = 0x07;
    
    ADCON0 = 0x40;
    ADCON1 = 0x84;
    
    TRISA = 0x03;
    TRISB = 0x00;
    TRISC = 0x80;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(200);
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt, txt1));
    LCD_Out(2,1,CopyConst2Ram(txt, txt2));
    
    UART1_Init(9600);
    Delay_ms(100);
    
    UART1_Write_Text(CopyConst2Ram(txt, txt4));
    
    for(cts_voltage = CTS_VOLTAGE_LOW, engine_temperature = ENGINE_TEMP_HIGH; cts_voltage <= CTS_VOLTAGE_HIGH, engine_temperature >= ENGINE_TEMP_LOW; cts_voltage = cts_voltage + CTS_VOLTAGE_STEP_SIZE, engine_temperature = engine_temperature - ENGINE_TEMPERATURE_STEP_SIZE) {
        FloatToStr(cts_voltage, txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        
        IntToStr((int)engine_temperature, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        
        stepper_angle_based_on_cts_voltage = (int)(((MAX_ANGLE - MIN_ANGLE) / (CTS_VOLTAGE_HIGH - CTS_VOLTAGE_LOW)) * cts_voltage + MIN_ANGLE);   //911.538*k = 45.0
        //stepper_angle_based_on_engine_temperature = (int)(((MAX_ANGLE - MIN_ANGLE) / (ENGINE_TEMP_LOW - ENGINE_TEMP_HIGH)) * engine_temperature + MAX_ANGLE);  //-88.8875*k = 3600
        
        IntToStr((int)stepper_angle_based_on_cts_voltage, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        
        no_of_steps_required = (int)stepper_angle_based_on_cts_voltage  / STEP_SIZE;
        IntToStr((int)no_of_steps_required, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        
        UART1_Write_Text(CopyConst2Ram(txt, txt6));
    }
 
    UART1_Write_Text(CopyConst2Ram(txt, txt6));
    
    cts_voltage = 0.0;
    engine_temperature = 0.0;
    stepper_angle_based_on_cts_voltage = 0;
    stepper_angle_based_on_engine_temperature = 0;
    no_of_steps_required= 0;
    
    UART1_Write_Text(CopyConst2Ram(txt, txt4));
    UART1_Write_Text(CopyConst2Ram(txt, txt6));
    UART1_Write_Text(CopyConst2Ram(txt, txt6));
                                        
    while(1) {
 
          raw_adc_value[0] = (long int)ADC_Read(0);
          Delay_us(20);
          raw_adc_value[1] = (long int)ADC_Read(1);
          Delay_us(20);
          
          if((previous_raw_adc_value[0] != raw_adc_value[0]) || (previous_raw_adc_value[1] != raw_adc_value[1])) {
              cts_voltage = (double)raw_adc_value[0] * ADC_0_REF / ADC_RESOLUTION;
              engine_temperature = (double)raw_adc_value[1] * ADC_1_REF / ADC_RESOLUTION;
 
              LCD_Out(2,4,CopyConst2Ram(txt, txt3));
              FloatToStr(cts_voltage, txt);
              strcat(txt, "V");
              LCD_Out(2,4,txt);
              
              LCD_Out(1,4,CopyConst2Ram(txt, txt3));
              FloatToStr_FixLen(engine_temperature, txt, 5);
              LCD_Out(1,4,txt);
              CustomChar(1,9);
              LCD_Out(1,10,"C");
 
              if(raw_adc_value[1] <= ENGINE_WARM_TEMPERATURE) {
                  stepper_angle_based_on_engine_temperature = (int)map(raw_adc_value[1], ENGINE_COLD_START_TEMPERATURE,
                                                          ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
 
              }
 
              if(raw_adc_value[0] <= CTS_V_HIGH) {
                  stepper_angle_based_on_cts_voltage = (int)map(raw_adc_value[0], CTS_V_LOW,
                                                          CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);
 
              }
              
              if(stepper_angle_based_on_engine_temperature == stepper_angle_based_on_cts_voltage) {
                  stepper_angle = stepper_angle_based_on_engine_temperature;
                  
                  IntToStr((int)stepper_angle, txt);
                  Ltrim(txt);
                  LCD_Out(1,12,txt);
 
                  if(previous_stepper_angle != stepper_angle) {
                      no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle, previous_stepper_angle);
                      direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);
 
                      FloatToStr(cts_voltage, txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
 
                      IntToStr((int)engine_temperature, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
 
                      IntToStr((int)stepper_angle_based_on_cts_voltage, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
 
                      no_of_steps_required = (int)stepper_angle_based_on_cts_voltage  / STEP_SIZE;
                      IntToStr((int)no_of_steps_required, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
 
                      UART1_Write_Text(CopyConst2Ram(txt, txt6));
 
                      switch(direction_of_steps) {
                            case 0:
                                   break;
                            case 1:       //if CCW, close valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 2;
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
 
                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index--];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 4;
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                            case 2:         //if CW, open valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index - 1;
                                   stepper_motor_sequence_lut_index = abs(stepper_motor_sequence_lut_index);
 
                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index++];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                      };
 
                      previous_stepper_angle = stepper_angle;
                  }
              }
 
              previous_raw_adc_value[0] = raw_adc_value[0];
              previous_raw_adc_value[1] = raw_adc_value[1];
          }
    }
}



- - - Updated - - -

I debugged this piece of test code and everything seems correct but stepper is not working as needed. When device is started with say engine temperature 0 and cts voltage 3.9 then motor rotates 3600 degrees = 240 steps and then if cts voltage is set to 0 and engine temperature to 40 then motor rotates anti clockwise only 45 degrees. It has to rotate 3600 - 45 degrees in reverse.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
void main() {
 
    no_of_steps_required = Get_No_Of_Steps_Required(3600, 0);
    direction_of_steps = Get_Required_Direction(3600, 0);
    
    no_of_steps_required = Get_No_Of_Steps_Required(45, 3600);
    direction_of_steps = Get_Required_Direction(45, 3600);
 
    no_of_steps_required = Get_No_Of_Steps_Required(270, 45);
    direction_of_steps = Get_Required_Direction(270, 45);
    
    CMCON = 0x07;



- - - Updated - - -

I got it working. The forum is updating the previous thread and so I will post working code after 30 minutes.
 

Attachments

  • IAC Valve Control - Revision P.rar
    143.3 KB · Views: 72
Last edited:

This was the piece of code which was causing the problem. See attached video. Do you think it is working properly ?

Code:
if(stepper_angle_based_on_engine_temperature == stepper_angle_based_on_cts_voltage) {
                  stepper_angle = stepper_angle_based_on_engine_temperature;
                  
                  IntToStr((int)stepper_angle, txt);
                  Ltrim(txt);
                  LCD_Out(1,12,txt);

                  if(previous_stepper_angle != stepper_angle) {
                      no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle, previous_stepper_angle);
                      direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);

                      FloatToStr(cts_voltage, txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));

                      IntToStr((int)engine_temperature, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));

                      [color=red]IntToStr((int)stepper_angle_based_on_cts_voltage, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));

                      no_of_steps_required = (int)stepper_angle_based_on_cts_voltage  / STEP_SIZE;
                      IntToStr((int)no_of_steps_required, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
			[/color]

                      UART1_Write_Text(CopyConst2Ram(txt, txt6));

                      switch(direction_of_steps) {
                            case 0:
                                   break;
                            case 1:       //if CCW, close valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 2;
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;

                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index--];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 4;
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                            case 2:         //if CW, open valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index - 1;
                                   stepper_motor_sequence_lut_index = abs(stepper_motor_sequence_lut_index);

                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index++];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                      };

                      previous_stepper_angle = stepper_angle;
                  }
              }


This is the fixed code and it is working, that is stepper motor is running but due to initail angle it is not working fine. How to fix it ?

The initial angle when device is started is the 0 degrees and in runtime the min angle is 45 degrees. This is causing the problem of stepper no rotating required angle. See attached video. Who can fix the problem ?

Code:
if(previous_stepper_angle != stepper_angle) {
                      no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle, previous_stepper_angle);
                      direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);

                      FloatToStr(cts_voltage, txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));

                      IntToStr((int)engine_temperature, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
			[color=blue]
                      IntToStr((int)stepper_angle, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));

                      IntToStr((int)no_of_steps_required, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
			[/color]
                      UART1_Write_Text(CopyConst2Ram(txt, txt6));

                      switch(direction_of_steps) {
                            case 0:
                                   break;
                            case 1:       //if CCW, close valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 2;
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;

                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index--];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 4;
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                            case 2:         //if CW, open valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index - 1;
                                   stepper_motor_sequence_lut_index = abs(stepper_motor_sequence_lut_index);

                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index++];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                      };

                      previous_stepper_angle = stepper_angle;
                  }


This is the latest full code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
#define ADC_0_REF 5.0
#define ADC_1_REF 500.0
 
#define ADC_RESOLUTION 1023.0
 
#define ENGINE_COLD_START_TEMPERATURE  0.0  //0 degree C
#define ENGINE_WARM_TEMPERATURE       82.0  //40 degree C
 
#define CTS_V_LOW    0.0  //0V
#define CTS_V_HIGH 798.0  //3.9V
 
#define IACV_PORT PORTB
 
#define STEP_SIZE 15.0
 
#define NO_ROTATION 0
#define CCW         1
#define CW          2
 
#define MIN_ANGLE    45.0
#define MAX_ANGLE 3600.0           // 15 degree / step, 240 steps, 3600 degree
 
#define ENGINE_TEMPERATURE_STEP_SIZE 1.0
#define CTS_VOLTAGE_STEP_SIZE        0.1
 
#define ENGINE_TEMP_LOW   0.0
#define ENGINE_TEMP_HIGH 40.0
 
#define CTS_VOLTAGE_LOW  0.0
#define CTS_VOLTAGE_HIGH 3.9
 
const code char txt1[] = "T: ";
const code char txt2[] = "V: ";
const code char txt3[] = "             ";
 
const code char txt4[] = "CTS V , ENGINE TEMPERATURE , STEPPER ANGLE , NO. OF STEPS\r\n";
const code char txt5[] = " , ";
const code char txt6[] = "\r\n";
 
char txt[63];
const char character[] = {6,9,9,6,0,0,0,0};
unsigned char stepper_motor_sequence[4] = {0x80, 0x20, 0x40, 0x10};
unsigned char engine_state_counter = 0;
char i = 0, j = 0;
unsigned char my_flags = 0;
long int raw_adc_value[2] = {0, 0};
long int previous_raw_adc_value[2] = {2048, 2048};
double engine_temperature = 0.0;
double cts_voltage = 0.0;
int stepper_angle_based_on_engine_temperature = 0;
int stepper_angle_based_on_cts_voltage = 0;
int stepper_angle = 0;
int previous_stepper_angle = 0;
unsigned char no_of_steps_required = 0;
char direction_of_steps = 0;
char stepper_motor_sequence_lut_index = 1;
 
char *CopyConst2Ram(char *dest, const code char *src){
    char *d;
 
    d = dest;
 
    for(;*dest++ = *src++;);
 
    return d;
}
 
void CustomChar(char pos_row, char pos_char) {
    char i;
    
    Lcd_Cmd(64);
    
    for (i = 0; i <= 7; i++) Lcd_Chr_CP(character[i]);
 
    Lcd_Chr(pos_row, pos_char, 0);
}
 
double map(double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
int Get_required_Angle_Of_Rotation(int angle, int previous_angle) {
    return (int)(angle - previous_angle);
}
 
unsigned char Get_No_Of_Steps_Required(int angle, int previous_angle) {
    if(angle < previous_angle) {
        return (unsigned char)((previous_angle - angle) / STEP_SIZE);
    }
    else if(angle > previous_angle) {
        return (unsigned char)((angle - previous_angle) / STEP_SIZE);
    }
    else if(angle == previous_angle) {
        return 0;
    }
}
 
char Get_Required_Direction(int angle, int previous_angle) {
    if(angle < previous_angle) {
        return 1;
    }
    else if(angle > previous_angle) {
        return 2;
    }
    if(angle == previous_angle) {
        return 0;
    }
}
 
void main() {
 
    CMCON = 0x07;
    
    ADCON0 = 0x40;
    ADCON1 = 0x84;
    
    TRISA = 0x03;
    TRISB = 0x00;
    TRISC = 0x80;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(200);
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt, txt1));
    LCD_Out(2,1,CopyConst2Ram(txt, txt2));
    
    UART1_Init(9600);
    Delay_ms(100);
    
    UART1_Write_Text(CopyConst2Ram(txt, txt4));
    
    for(cts_voltage = CTS_VOLTAGE_LOW, engine_temperature = ENGINE_TEMP_HIGH; cts_voltage <= CTS_VOLTAGE_HIGH, engine_temperature >= ENGINE_TEMP_LOW; cts_voltage = cts_voltage + CTS_VOLTAGE_STEP_SIZE, engine_temperature = engine_temperature - ENGINE_TEMPERATURE_STEP_SIZE) {
        FloatToStr(cts_voltage, txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        
        IntToStr((int)engine_temperature, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        
        stepper_angle_based_on_cts_voltage = (int)(((MAX_ANGLE - MIN_ANGLE) / (CTS_VOLTAGE_HIGH - CTS_VOLTAGE_LOW)) * cts_voltage + MIN_ANGLE);   //911.538*k = 45.0
 
        IntToStr((int)stepper_angle_based_on_cts_voltage, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        UART1_Write_Text(CopyConst2Ram(txt, txt5));
        
        no_of_steps_required = (int)stepper_angle_based_on_cts_voltage  / STEP_SIZE;
        IntToStr((int)no_of_steps_required, txt);
        Ltrim(txt);
        UART1_Write_Text(txt);
        
        UART1_Write_Text(CopyConst2Ram(txt, txt6));
    }
 
    UART1_Write_Text(CopyConst2Ram(txt, txt6));
    
    cts_voltage = 0.0;
    engine_temperature = 0.0;
    stepper_angle_based_on_cts_voltage = 0;
    stepper_angle_based_on_engine_temperature = 0;
    no_of_steps_required= 0;
    
    UART1_Write_Text(CopyConst2Ram(txt, txt4));
    UART1_Write_Text(CopyConst2Ram(txt, txt6));
    UART1_Write_Text(CopyConst2Ram(txt, txt6));
    
    while(1) {
 
          raw_adc_value[0] = (long int)ADC_Read(0);
          Delay_us(20);
          raw_adc_value[1] = (long int)ADC_Read(1);
          Delay_us(20);
          
          if((previous_raw_adc_value[0] != raw_adc_value[0]) || (previous_raw_adc_value[1] != raw_adc_value[1])) {
              cts_voltage = (double)raw_adc_value[0] * ADC_0_REF / ADC_RESOLUTION;
              engine_temperature = (double)raw_adc_value[1] * ADC_1_REF / ADC_RESOLUTION;
 
              LCD_Out(2,4,CopyConst2Ram(txt, txt3));
              FloatToStr(cts_voltage, txt);
              strcat(txt, "V");
              LCD_Out(2,4,txt);
              
              LCD_Out(1,4,CopyConst2Ram(txt, txt3));
              FloatToStr_FixLen(engine_temperature, txt, 5);
              LCD_Out(1,4,txt);
              CustomChar(1,9);
              LCD_Out(1,10,"C");
 
              if((raw_adc_value[1] >= ENGINE_COLD_START_TEMPERATURE) && (raw_adc_value[1] <= ENGINE_WARM_TEMPERATURE)) {
                  stepper_angle_based_on_engine_temperature = (int)map(raw_adc_value[1], ENGINE_COLD_START_TEMPERATURE,
                                                          ENGINE_WARM_TEMPERATURE, MAX_ANGLE, MIN_ANGLE);
 
              }
 
              if((raw_adc_value[0] >= CTS_V_LOW) && (raw_adc_value[0] <= CTS_V_HIGH)) {
                  stepper_angle_based_on_cts_voltage = (int)map(raw_adc_value[0], CTS_V_LOW,
                                                          CTS_V_HIGH, MIN_ANGLE, MAX_ANGLE);
 
              }
              
              if(stepper_angle_based_on_engine_temperature == stepper_angle_based_on_cts_voltage) {
                  stepper_angle = stepper_angle_based_on_engine_temperature;
                  
                  IntToStr((int)stepper_angle, txt);
                  Ltrim(txt);
                  LCD_Out(1,12,txt);
 
                  if(previous_stepper_angle != stepper_angle) {
                      no_of_steps_required = Get_No_Of_Steps_Required(stepper_angle, previous_stepper_angle);
                      direction_of_steps = Get_Required_Direction(stepper_angle, previous_stepper_angle);
 
                      FloatToStr(cts_voltage, txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
 
                      IntToStr((int)engine_temperature, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
 
                      /*
                      IntToStr((int)stepper_angle, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
                      */
                      
                      IntToStr((int)Get_required_Angle_Of_Rotation(stepper_angle, previous_stepper_angle), txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
                      UART1_Write_Text(CopyConst2Ram(txt, txt5));
 
                      IntToStr((int)no_of_steps_required, txt);
                      Ltrim(txt);
                      UART1_Write_Text(txt);
 
                      UART1_Write_Text(CopyConst2Ram(txt, txt6));
 
                      switch(direction_of_steps) {
                            case 0:
                                   break;
                            case 1:       //if CCW, close valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 2;
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
 
                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index--];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index + 4;
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                            case 2:         //if CW, open valve
                                   stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index - 1;
                                   stepper_motor_sequence_lut_index = abs(stepper_motor_sequence_lut_index);
 
                                   for(i = 0; i < no_of_steps_required; i++) {
                                       IACV_PORT = (IACV_PORT & 0x0F) | stepper_motor_sequence[stepper_motor_sequence_lut_index++];
                                       Delay_ms(100);
                                       stepper_motor_sequence_lut_index = stepper_motor_sequence_lut_index % 4;
                                   }
                                   break;
                      };
 
                      previous_stepper_angle = stepper_angle;
                  }
              }
 
              previous_raw_adc_value[0] = raw_adc_value[0];
              previous_raw_adc_value[1] = raw_adc_value[1];
          }
    }
}

 

Attachments

  • IAC Valve Control - Revision T.rar
    626 KB · Views: 67

After two days of hard work the project completes successfully. See the attached video for working. To make small video I have reduced the valve partially open and full open angles.

I will post the complete project after asking the student.
 

Attachments

  • Proteus Simulation Video #3.rar
    337.4 KB · Views: 76

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top