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.

Need Help: Integrating lamps dimmer with blinds (using stepper motor)

Status
Not open for further replies.
Like this?

Code:
void change_intensity()                            
 {
        static unsigned int motor_flagA;
        static unsigned int inten_flagA;
        
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((ldr1 <= 500) && (motor_flagA < 1))
        {
            turn_A(ARIGHT,23);
            motor_flagA++;
        }
        
        #asm("cli")
        if((PORTB.0 == 1) && (ldr1 <= 500) && (motor_flagA == 1))
        {
            if(x > 1)
                {  
                    x = x - 1;
                }
        }
        
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds        
        if((PORTB.0 == 1) && (ldr1 >= 550))
        {
            if(x < 280)
                { 
                    x = x + 1;
                    inten_flagA++;
                }
        }
        #asm("sei")        

        if((ldr1 >= 550) && (inten_flagA == 1) && (motor_flagA == 1))
        {
            turn_A(ALEFT,23);
            motor_flagA = 0;
            inten_flagA = 0;    
        }
        
        [COLOR="#FF0000"]// But here will be the second motor, can I disable it again[/COLOR]
           
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((PORTB.1 == 1) && (ldr2 <= 500))
        {
            if(y > 1)
                {
                    y = y - 1;
                }
        }
        
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds
        if((PORTB.1 == 1) && (ldr2 >= 550))
        {
            if(y < 280)
                {
                    y = y + 1;
                }
        }
          
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((PORTB.2 == 1) && (ldr3 <= 500))
        {
            if(z > 1)
                {
                    z = z - 1;
                }
        }
           
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds
        if((PORTB.2 == 1) && (ldr3 >= 550))
        {
            if(z < 280)
                {
                    z = z + 1;
                }
        }
 }
 

// But here will be the second motor, can I disable it again

Yes, you can apply cli() sei() in many separate parts inside the function, that is not a problem.
 

Ok, so in my forever loop I don't need to disable the interrupt right?

like this:
Code:
while(1)
{
        display_adc();
        change_intensity();
}

- - - Updated - - -

oooo

It works actually, but I get this:
oo.png
when the motor turns.

When it stop, everything else are fine!
 

No since you do it in the parts that need it inside change_intensity()

- - - Updated - - -

Review your code and see what can be causing it, it is not x,y,z
 

I make it to be like this:

Code:
void change_intensity()
 {
        static unsigned int motor_flagA = 0;
        static unsigned int motor_flagB = 0;
        static unsigned int motor_flagC = 0;
                
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((ldr1 <= 300) && (motor_flagA < 1))
        {
            turn_A(ARIGHT,23);
            motor_flagA++;
        }
        
        #asm("cli")   
        if((PORTB.0 == 1) && (ldr1 <= 300) && (motor_flagA == 1))
        {
            if(x > 1)
            {  
                x = x - 1;
            }
        }
        
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds        
        if((PORTB.0 == 1) && (ldr1 >= 350))
        {
            if(x < 280)
            { 
                x = x + 1;
            }
        }
        
        #asm("sei")
        
        if((ldr1 >= 350) && (x == 280) && (motor_flagA == 1))
        {
            turn_A(ALEFT,23);
            motor_flagA = 0;   
        }        
           
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((ldr2 <= 300) && (motor_flagB < 1))
        {
            turn_B(BRIGHT,23);
            motor_flagB++;
        }

        #asm("cli")
        if((PORTB.1 == 1) && (ldr2 <= 300) && (motor_flagB == 1))
        {
            if(y > 1)
            {
                y = y - 1;
            }
        }
        
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds
        if((PORTB.1 == 1) && (ldr2 >= 350))
        {
            if(y < 280)
            {
                y = y + 1;
            }
        }
        
        #asm("sei")
        if((ldr2 >= 350) && (y == 280) && (motor_flagB == 1))
        {
            turn_B(BLEFT,23);
            motor_flagB = 0;   
        }
        
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((ldr3 <= 300) && (motor_flagC < 1))
        {
            turn_C(CRIGHT,23);
            motor_flagC++;
        }        
        
        #asm("cli")   
        if((PORTB.2 == 1) && (ldr3 <= 300) && (motor_flagC == 1))
        {
            if(z > 1)
            {
                z = z - 1;
            }
        }
           
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds
        if((PORTB.2 == 1) && (ldr3 >= 350))
        {
            if(z < 280)
            {
                z = z + 1;
            }
        }
        
        #asm("sei")
        if((ldr3 >= 350) && (z == 280) && (motor_flagC == 1))
        {
            turn_C(CLEFT,23);
            motor_flagC = 0;   
        }        
 }

I've reviewed it, but I don't know why. Do you see something wrong there?
 
Last edited:

Hmmm,

Just wondering this part:

Code:
unsigned int motor_stepA[4] = {0b00101000, 0b00110000, 0b01010000, 0b01001000};   [COLOR="#FF0000"]// This and the others and also below[/COLOR]

 void turn_A(unsigned char directionA, int stepA)
 {
    static unsigned char i = 0;
    unsigned int j = 0;
    while(j <= stepA)
    {
        j++;
        if(directionA)
        {
            i++;
        }
        else
            {
                i--;
            }
        if(i == 255)
        {
            i = 3;
        }
        else
            if(i == 4)
            {
                i = 0;
            }
        PORTB = motor_stepA[i];     // [COLOR="#FF0000"]I connected the dimmers to PORTB.0 1 and 2. May this part affect those pulses?[/COLOR]
        delay_ms(50);
    }
 }
 
Last edited:

PORTB = motor_stepA; [


This line assigns a new value to all bits of the port ans will also change bits 0 and 1, if you are using only bits 3-6 for the motor use a mask

Code:
PORTB = (PORTB & 0b10000111) | motor_stepA[i];
 

Well, you're right about that. Now the other problems come again, fiuhhh:-(

First, during the execution, the external interrupt signal is suddenly changing from 5 Volt into around 2 Volt and stay at 2 Volt as shown by the picture below:
ext.png
Will it still detected by my AVR? I'm not sure what is causing this.

Second, when I tried to zoom out the oscilloscope, I got this:
lost.png

That makes my lamps blink.
 

First, during the execution, the external interrupt signal is suddenly changing from 5 Volt into around 2 Volt and stay at 2 Volt as shown by the picture below:

I have no idea what this graph represents

Second, when I tried to zoom out the oscilloscope, I got this:
is it the same when you zoom in?
 

I have no idea what this graph represents

It is Zero Crossing Signal which is connected to the INT0 pin (PORTD.2). External interrupt occurs every 10 ms and it will activate timer0 (TCCR0).

is it the same when you zoom in?

Yes, off course.


I have tested my real hardware and I saw the lamps is blinking but motors work well.
 

Post your motor_stepB and C and the place you set them like PORTB = (PORTB & 0b10000111) | motor_stepA;
 


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
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
#include <mega8535.h>
 #include <stdio.h>
 #include <delay.h>
 #include <stdint.h>
 #define ALEFT 0
 #define ARIGHT 1
 #define BLEFT 0
 #define BRIGHT 1
 #define CLEFT 0
 #define CRIGHT 1
 
 unsigned char buf[10];
 volatile unsigned int ldr1;
 volatile unsigned int ldr2;
 volatile unsigned int ldr3;
 
 unsigned int count = 0;
 
 
 volatile unsigned int x = 280;
 volatile unsigned int y = 280;
 volatile unsigned int z = 280;
 
 unsigned int motor_stepA[4] = {0b00101000, 0b00110000, 0b01010000, 0b01001000};
 unsigned int motor_stepB[4] = {0b00101000, 0b00110000, 0b01010000, 0b01001000};
 unsigned int motor_stepC[4] = {0b00101000, 0b00110000, 0b01010000, 0b01001000};
    
 // Alphanumeric LCD functions
 #include <lcd.h>
 #asm
 .equ __lcd_port=0x15 ;PORTC
 #endasm
 
 // External Interrupt 0 service routine
 interrupt [EXT_INT0] void ext_int0_isr(void)
 {
    // Start  Timer 0
    TCCR0 = 0x02;
 }
 
 // Timer 0 overflow interrupt service routine
 interrupt [TIM0_OVF] void timer0_ovf_isr(void)
 {
    // Local variables initialization
    static unsigned int pulse_flag = 0;
    // Reinitialize Timer 0 value
    TCNT0=0xD3;     
    // Increment count every 50 us
    count++;
    
    // Front lamp
    if(count == x)
        {
            PORTB.0 = 0;
        }
    else
        if(count == x + 1)
            {
                PORTB.0 = 1;
                pulse_flag++;
            }
                
    // Middle lamp        
    if(count == y)
        {
            PORTB.1 = 0;
        }
    else
        if(count == y + 1)
            {
                PORTB.1 = 1;
                pulse_flag++;
            }
 
    // Back lamp
    if(count == z)
        {
            PORTB.2 = 0;
        }
    else
        if(count == z + 1)
            {
                PORTB.2 = 1;
                pulse_flag++;
            }
     
    // Stop timer when all pulses are completed
    if(pulse_flag >= 3)
        {
            // Clear flag
            pulse_flag = 0;
            // Clear count
            count = 0;
            // Stop the timer
            TCCR0 = 0;
            // Reset the timer
            TCNT0 = 0;
            // Check ADC
           
        }  
 }
 
 #define ADC_VREF_TYPE 0x40
 // Read the AD conversion result
 unsigned int read_adc(unsigned char adc_input)
 {
    ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
    // Delay needed for the stabilization of the ADC input voltage
    delay_us(10);
    // Start the AD conversion
    ADCSRA|=0x40;
    // Wait for the AD conversion to complete
    while ((ADCSRA & 0x10)==0);
    ADCSRA|=0x10;
    return ADCW;
 }
 
 void turn_A(unsigned char directionA, int stepA)
 {
    static unsigned char i = 0;
    unsigned int j = 0;
 
    while(j <= stepA)
    {
        j++;
 
        if(directionA)
        {
            i++;
        }
        else
            {
                i--;
            }
 
        if(i == 255)
        {
            i = 3;
        }
        else
            if(i == 4)
            {
                i = 0;
            }
 
        PORTB = (PORTB & 0b10000111) | motor_stepA[i];          // PORTB.0 1 2 and 7 as output
        delay_ms(50);
    }
 }
 
 void turn_B(unsigned char directionB, int stepB)
 {
    static unsigned char k = 0;
    unsigned int l = 0;
 
    while(l <= stepB)
    {
        l++;
 
        if(directionB)
        {
            k++;
        }
        else
            {
                k--;
            }
 
        if(k == 255)
        {
            k = 3;
        }
        else
            if(k == 4)
            {
                k = 0;
            }
 
        PORTD = (PORTD & 0b10000111) | motor_stepB[k];         // PORTD.0 1 2 as input
        delay_ms(50);
    }
 }
 
 void turn_C(unsigned char directionC, int stepC)
 {
    static unsigned char m = 0;
    unsigned int n = 0;
 
    while(n <= stepC)
    {
        n++;
 
        if(directionC)
        {
            m++;
        }
        else
            {
                m--;
            }
 
        if(m == 255)
        {
            m = 3;
        }
        else
            if(m == 4)
            {
                m = 0;
            }
            
        PORTA = (PORTA & 0b10000111) | motor_stepC[m];      // PORTA.0 1 2 as input
        delay_ms(50);
    }
 }
 
 
 void display_adc()
 {
    ldr1=read_adc(0);
    lcd_gotoxy(0,0);
    sprintf(buf,"L1:%d%d%d%d",ldr1/1000,(ldr1%1000)/100,(ldr1%1000%100)/10,ldr1%1000%100%10);
    lcd_puts(buf);
        
    ldr2=read_adc(1);
    lcd_gotoxy(9,0);
    sprintf(buf,"L2:%d%d%d%d",ldr2/1000,(ldr2%1000)/100,(ldr2%1000%100)/10,ldr2%1000%100%10);
    lcd_puts(buf);
        
    ldr3=read_adc(2);
    lcd_gotoxy(0,1);
    sprintf(buf,"L3:%d%d%d%d", ldr3/1000,( ldr3%1000)/100,( ldr3%1000%100)/10, ldr3%1000%100%10);
    lcd_puts(buf);
 }
 
 void change_intensity()
 {
 
        static unsigned int motor_flagA = 0;
        static unsigned int motor_flagB = 0;
        static unsigned int motor_flagC = 0;
                
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((ldr1 <= 300) && (motor_flagA < 1))
        {
            turn_A(ARIGHT,23);
            motor_flagA++;
        }
        
        #asm("cli")   
        if((PORTB.0 == 1) && (ldr1 <= 300) && (motor_flagA == 1))
        {
            if(x > 1)
            {  
                x = x - 1;
            }
        }
        
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds        
        if((PORTB.0 == 1) && (ldr1 >= 350))
        {
            if(x < 280)
            { 
                x = x + 1;
            }
        }
        
        #asm("sei")
        
        if((ldr1 >= 350) && (x == 280) && (motor_flagA == 1))
        {
            turn_A(ALEFT,23);
            motor_flagA = 0;   
        }        
           
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((ldr2 <= 300) && (motor_flagB < 1))
        {
            turn_B(BRIGHT,23);
            motor_flagB++;
        }
 
        #asm("cli")
        if((PORTB.1 == 1) && (ldr2 <= 300) && (motor_flagB == 1))
        {
            if(y > 1)
            {
                y = y - 1;
            }
        }
        
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds
        if((PORTB.1 == 1) && (ldr2 >= 350))
        {
            if(y < 280)
            {
                y = y + 1;
            }
        }
        
        #asm("sei")
        if((ldr2 >= 350) && (y == 280) && (motor_flagB == 1))
        {
            turn_B(BLEFT,23);
            motor_flagB = 0;   
        }
        
        // If light intensity below the setpoint, open blinds, and shorten the firing delay
        if((ldr3 <= 300) && (motor_flagC < 1))
        {
            turn_C(CRIGHT,23);
            motor_flagC++;
        }        
        
        #asm("cli")   
        if((PORTB.2 == 1) && (ldr3 <= 300) && (motor_flagC == 1))
        {
            if(z > 1)
            {
                z = z - 1;
            }
        }
           
        // If light intensity greater than the setpoint, increase the firing delay, and close blinds
        if((PORTB.2 == 1) && (ldr3 >= 350))
        {
            if(z < 280)
            {
                z = z + 1;
            }
        }
        
        #asm("sei")
        if((ldr3 >= 350) && (z == 280) && (motor_flagC == 1))
        {
            turn_C(CLEFT,23);
            motor_flagC = 0;   
        }        
 }
 
 void main(void)
 {
    // Input/Output Ports initialization
    PORTA=0x00;
    DDRA=0xF8;
    PORTB=0x07;
    DDRB=0xFF;
    PORTC=0x00;
    DDRC=0x00;
    PORTD=0x00;
    DDRD=0xF8;
 
    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: 1500.000 kHz
    // Mode: Normal top=0xFF
    // OC0 output: Disconnected
    TCCR0 = 0x02;
    TCNT0 = 0xD3;
    OCR0 = 0x00;
 
    // External Interrupt(s) initialization
    // INT0: On
    // INT0 Mode: Falling Edge
    GICR|=0x40;
    MCUCR=0x02;
    MCUCSR=0x00;
    GIFR=0x40;
 
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x01;
 
    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;
 
    // ADC initialization
    ADMUX=ADC_VREF_TYPE & 0xff;
    ADCSRA=0x84;
    SFIOR&=0xEF;
 
    // Alphanumeric LCD initialization
    // Characters/line: 16
    lcd_init(16);
 
    // Global enable interrupts
    #asm("sei")
 
    while (1)
      {
        display_adc();
        change_intensity();
      }
 }

 
Last edited:

Code:
PORTD = (PORTD & [COLOR="#FF0000"]0b00000000[/COLOR]) | motor_stepB[k];         // PORTD.0 1 2 as input

PORTA = (PORTA & [COLOR="#FF0000"]0b00000000[/COLOR]) | motor_stepC[m];      // PORTA.0 1 2 as input

Really? :roll:
 

Uhhhmmmm.....

Ok I change it back as what you suggested in post #28. The previous code has been edited.

- - - Updated - - -

In case you want to see by yourself, I attach the complete file.
 

Attachments

  • New folder.zip
    127.7 KB · Views: 35

Well:

Code:
AND operator is used to see if a bit is set or clear
Then OR operator is used to set bit 0 in first condition and then store the result back into it. 
PORTB = (PORTB & 0b10000111) | motor_stepA[i];        // if PORTB is cleared then the first condition gives zero
PORTB =  0 | motor_stepA[i];           //   OR operator will always true whenever one or both of the condition contain 1

Am I right?
 

Am I right?
No

I have no idea why you decided to make a complicated project when you are missing some basics of programming.
I suggest you read the tutorial carefully, there is no condition involved in the code.
 

I'm sorry:x

Let me try again

Code:
PORTB = (PORTB & 0b10000111) | motor_stepA[i]

I connected the motors to PORTB. 3 4 5 6, which means I need to clear the bits that I don't need (0 1 2 and 7).
What I want is : 0b01111000
So I need an inverted MASK of it : 0b10000111
To clear the bit, the inverted mask must be AND-ed with the previous variable so it become PORTB & inverted mask = PORTB & 0b10000111


If I write PORTD = (PORTD & 0b00000000) | motor_stepB[k];
This is wrong because 0b00000000 is not the correct inverted mask


Hope I am right?
 

Hope I'am right now?
Not yet ;-)

I connected the motors to PORTB. 3 4 5 6, which means I need to clear the bits that I don't need (0 1 2 and 7).
It is exactly the opposite, you want to clear the motor pin bits 3 4 5 6 and preserve the existing value to the other bits 0 1 2 and 7

Any bit ANDed with 1 preserves the value it had
Any bit ANDed with 0 gets cleared (results to 0)

Any bit ORed with 1 gets set (results to 1)
Any bit ORed with 0 preserves the value it had

PORTB = PORTB & 0b10000111

bits 0, 1, 2, 7 will be reserved since they are ANDed with 1
bits 3, 4, 5, 6 will be cleared since they are ANDed with 0

Now that the motor pins have been cleared you OR them with the new value which is one of 0b00101000, 0b00110000, 0b01010000, 0b01001000

Note that the bits 0, 1, 2, 7 are 0 in all four values so they are not going to change the value of these bits in the port since we now apply OR

So all this leads to PORTB = (PORTB & 0b10000111) | motor_stepA

- - - Updated - - -

If you wanted to add an additional safety so that bits 0, 1, 2, 7 of motor_stepA will not change the port bits even if they are set to 1 by mistake then you add a mask

PORTB = (PORTB & 0b10000111) | (motor_stepA & 0b01111000)
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top