Multiple servos using demux

Hi all!
My project is about managing servo motors using keypad. Only one servo can be opened at the same time. Initial state - all servos are in default state.
See small demo for details.
Everything seems easy, but:
I use Arduino Uno and decoder 74HC238.
I set control pulse using Arduino digital pin. Code here
As you can see on video, I have some noise/interference on the servos input signals.
Does someone have any ideas how to prevent this?

Also there is some problem with output signal from Demux.
When I click keypad button '2', the servos №2, 3, 5 open.
The same with keypad 4 - servo 4 and 7.
I compared binary formats, but saw no dependence.
2 -> 0010
3 -> 0011
5 -> 0101

4 -> 0100
7 -> 0111

Thank you for any help!

That CodeHere link seems to be to a picture. It is no good showing a picture of code - how can I load it into a text editor?

Also, don't expect people to go to another website for your code. Post it here. Use the code button </> so it looks like this

...R

Ok, attached code here:

void loop(){
	// keypad start
	keyboardValue = analogRead(keyboardPin); // read the keyboard value (0 - 1023)
	while (keyboardValue < 25){
		//do nothing until a key is pressed
		keyboardValue = analogRead(keyboardPin);
		servo.attach(3);
// FOR SERVO
		digitalWrite(3, HIGH);
		delayMicroseconds(544); // Approximately 10% duty cycle @ 1KHz
		digitalWrite(3, LOW);
		delayMicroseconds(20000-544);
// SERVO
		//delay(50);
	}//end of do nothing till a key is pressed
	readkeyboard(); //get the value of key being pressed "keypressed" i.e. 0-9
	// keypad end
}

OK, so we are talking here about standard radio-control model servos are we not?

I do not know why you have chosen a 74HC238. Servos are multiplexed, eight or nine at a time by using a 74HC4017 and using two control lines, reset and clock.

After resetting, you simply clock it with a series of pulses whose successive intervals correspond to the pulse values for each servo in turn. The duration of the pulse at each of the nine outputs "1" to "9" controls the respective servo.

Generally speaking, you are expected to pulse every servo at least every 20 ms, so you do not just feed pulses to only one to the exclusion of others. If not pulsed regularly, servos may fail to hold their position.

happyBanshee:
Ok, attached code here:

Please post the complete code so that people can try to compile it to test it.

...R

Paul__B:
OK, so we are talking here about standard radio-control model servos are we not?

I`m not sure I understand what do you mean. I try to implement locks which could be opened by special combination on the key pad.
Ex: I click btn 8 -> lock 8 opens and closes in a minute.
btn 2 -> lock 2 opens and closes in a minute.

Paul__B:
I do not know why you have chosen a 74HC238. Servos are multiplexed, eight or nine at a time by using a 74HC4017 and using two control lines, reset and clock.

As I understand this counter allows to operate all locks in the same time. They just pass ''1" in series: one after another. But I don`t need this. I guess my demo attached is pretty clear. Tell me please, if not.

Thanks.

Full code here:

#include <SPI.h>
#include <LiquidCrystal.h>
#include <Servo.h> 
LiquidCrystal lcd(10);
Servo servo;
char keypressed = 0;
int keyboardPin = 0; // Analog input pin that the keypad is attached to
int keyboardValue = 0;  // value read from the keyboard
//int pincodeSize = 4,
int numCount = 0;
char pincode[4];
//int presses = 2;
byte pins[] = {8,7,5};
int state;

void setup(){
 Serial.begin(9600); //hardware serial to PC
 // setup LCD number of columns ans rows
 lcd.begin(16, 2);
 // print message on LCd
 lcd.print("Enter the pin:");
 lcd.setCursor(0,1);    
 // demux
 pinMode(8, OUTPUT);
 pinMode(7, OUTPUT);
 pinMode(5, OUTPUT);
 //pinMode(2, OUTPUT);
 digitalWrite(8, LOW);
 digitalWrite(7, LOW);
 digitalWrite(5, LOW);
 // DEMUX E3
 digitalWrite(3, HIGH);



}
void loop(){
 // keypad start
 keyboardValue = analogRead(keyboardPin); // read the keyboard value (0 - 1023)
 while (keyboardValue < 25){
 //do nothing until a key is pressed
 keyboardValue = analogRead(keyboardPin);
 servo.attach(3);

 digitalWrite(3, HIGH);
 delayMicroseconds(544); // Approximately 10% duty cycle @ 1KHz
 digitalWrite(3, LOW);
 delayMicroseconds(20000-544);
 //delay(50);
 }//end of do nothing till a key is pressed
 readkeyboard(); //get the value of key being pressed "keypressed" i.e. 0-9
 // keypad end




}

void OpenServo(int key){
 Serial.println("key");
 Serial.println(key);

 /* convert presses to binary and store it as a string */
 //key=1 && key=0;
 key=key-1;
 String binNumber = String(key, BIN);

 /* get the length of the string */
 int binLength = binNumber.length(); 
 /*if(binLength==1){
 binNumber ="00"+binNumber;
 }
 else if(binLength==2){
 binNumber ="0"+binNumber;
 }*/
 Serial.println("binNumber");

 Serial.println(binNumber);
 //Serial.println("binNumber");
 // Serial.println(binNumber);
 if(key <= 255) { // if we have less or equal to 255 presses
 // here is the scary code
 for(int i = 0, x = 1; i < binLength; i++, x+=2) { 
 if(binNumber[i] == '0') state = LOW;
 if(binNumber[i] == '1') state = HIGH;
 digitalWrite(pins[i], state);
 } 
 }

}

void LcdClearLine(int r)
{
 lcd.setCursor(0, r);
 for (int ii = 0; ii < 16; ii = ii + 1) {
 lcd.print(" ");
 }
}

//read the keyboard routine
void readkeyboard(){
 keyboardValue = analogRead(keyboardPin); // read the value (0-1023)
 if (keyboardValue <25){keypressed = 0;}
 if ((keyboardValue >25) && (keyboardValue < 67)){keypressed = '1';}
 if ((keyboardValue >67) && (keyboardValue < 108)){keypressed = '2';}
 if ((keyboardValue >108) && (keyboardValue < 162)){keypressed = '3';}
 if ((keyboardValue >162) && (keyboardValue < 253)){keypressed = '4';}
 if ((keyboardValue >253) && (keyboardValue < 361)){keypressed = '5';}
 if ((keyboardValue >361) && (keyboardValue < 479)){keypressed = '6';}
 if ((keyboardValue >479) && (keyboardValue < 619)){keypressed = '7';}
 if ((keyboardValue >619) && (keyboardValue < 765)){keypressed = '8';}
 if ((keyboardValue >765) && (keyboardValue < 819)){keypressed = '9';}
 if ((keyboardValue >819) && (keyboardValue < 889)){keypressed = '*';}
 if ((keyboardValue >889) && (keyboardValue < 938)){keypressed = '0';}
 if (keyboardValue >938){keypressed = '#';}
 //NOTE: the values used above are all halfway between the value obtained with each keypress in previous test sketch
 while (keyboardValue > 25) {
 //delay (100);
 keyboardValue = analogRead(keyboardPin); // read the value (0-1023)
 }//wait until key no longer being pressed before continuing
 switch (keypressed) {
 case '#':
 Serial.println("ENTER");
 LcdClearLine(0);
 lcd.setCursor(0, 0);
 lcd.print("Welcome");
 lcd.setCursor(0, 1);
 LcdClearLine(1);          
 // send pin to server to validate
 break;
 case '*':
 Serial.println("RESET");
 // clean entered pincode
 numCount = 0;
 //pincode = char[4];
 LcdClearLine(0);
 lcd.setCursor(0, 0);
 lcd.print("Enter the pin:");
 LcdClearLine(1);
 lcd.setCursor(0, 1);
 break;
 default:
 //if(numCount != 4){
 pincode[numCount] = (char) keypressed;
 Serial.println("NUM");
 lcd.write(keypressed);
 OpenServo(keypressed- '0');
 numCount++;
 //}
 }

 Serial.println(keypressed);  // print the value back to the Serial view window on your PC
 // delay(1000);  // wait 1000 milliseconds before the next loop
}
//end of read the keyboard routine

happyBanshee:
I'm not sure I understand what do you mean. I try to implement locks which could be opened by special combination on the key pad.

When we are referring to servos, I presume we are talking about these things:


They operate by being fed a continuous stream of pulses whose length varies between 1 and 2 ms, with 1.5 ms corresponding to a "centre" position.

happyBanshee:
As I understand this counter allows to operate all locks in the same time. They just pass ''1" in series: one after another. But I don`t need this.

I think you do need to control all servos at the same time and therefore explained how to do it most efficiently. If you do not send control pulses to a servo, it ceases to hold its position against forces tending to move it. This may not matter if the friction in the mechanism is sufficient to prevent further movement, but if you only address one servo at a time, there is nothing to prevent the others drifting or being moved by external pressure.

happyBanshee:
I guess my demo attached is pretty clear. Tell me please, if not.

Without examining it in too much detail, it is pretty clear that you are only controlling and holding the position of one servo at any one time. They may also "glitch" each time you start feeding them pulses

I have no idea what the code in Reply #5 is supposed to do. It seems to be a complete bird's nest with, for example, code about keyboard IFs all over the place. There are delay()s and blocking WHILEs all over the place.

The function OpenServo() doesn't have a single reference to a servo within it.

Have a look at planning and implementing a program. If this was my project my loop() would be (assuming I understand the task correctly)

void loop() {
  readKeyPad();
  updateLCD();
  validateKeyCode();
  operateLock();
}

Each function should be written to take the minimum amout of time so that loop() repeats as quickly as possible.

...R

Well, looks like I still miss something, I can not understand the logic.
I tried the example with Aduino and 74HC4017. I used code attached there, but I got this result .
In the example the Mega is used, but I need Uno. So, mayb I need update the code somehow.
Help me please. My wild guessing drives me crazy.

happyBanshee:
My wild guessing drives me crazy.

How can we do any more than make wild guesses if you won't post your latest code ?

It doesn't help that you give no impression of having read any of the posts where people have already tried to help you.

...R

I try ro follow the advices, but I don`t understand how to assemble everythng.

Now I have Arduino Mega.
Diagram: here
Demo: here
Code: gist.github

As I can see after 5 iterations reset enables.

If you want me to look at your code post it here so I don't have to go to some other web page to find it.

If it is short enough (and preferably it is) include it in your Post. Otherwise add your .ino file as an attachment.

Help us to help you.

...R

Code is here:

#include <SPI.h>
#include <LiquidCrystal.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#include <ctype.h>
#include <math.h>
#include <avr/io.h>


#define HW_4017_RESET_PIN         47
#define HW_4017_CLOCK_PIN         13

#define _4017_RESET_PORT        PORTB
#define _4017_CLOCK_PORT        PORTB
#define _4017_RESET_DDR         DDRB
#define _4017_CLOCK_DDR         DDRB
#define _4017_RESET_PIN         PINB0
#define _4017_CLOCK_PIN         PINB1

#define SERVO_OCR		OCR1A
#define SERVO_ENABLE            OCIE1A
#define SERVO_FLAG		OCF1A
#define SERVO_FORCE		FOC1A
#define SERVO_COM0		COM1A0
#define SERVO_COM1		COM1A1

#if defined (__AVR_ATmega8__)
#define TIMER_SK	TIMSK
#define TIMER_IFR	TIFR
#define FORCE_REG	TCCR1A
#else
#define TIMER_SK	TIMSK1
#define TIMER_IFR	TIFR1
#define FORCE_REG	TCCR1C
#endif

#ifndef _BV
#define _BV(bit) (1 << (bit))
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define CLOCK 16
#define SYS_TICS_OF_USEC(us) (uint16_t)((us)*CLOCK)

#define Chop(_x, _min, _max) ( (_x) < (_min) ? (_min) : (_x) > (_max) ? (_max) : (_x) )
#define SetServo(x, v) servo_widths[x] = SYS_TICS_OF_USEC(Chop(v,700,2400));

#define _4017_NB_CHANNELS 10

#define ON  1
#define OFF 0
#define OneSecond  1000

#define ledPin	13

unsigned int servo_widths[_4017_NB_CHANNELS];

void Servo_4017_Set_Pulse_Width( int ServoNum, int pulseWidth )
{
	servo_widths[ServoNum] = SYS_TICS_OF_USEC(pulseWidth);
}
void Servo_4017_init( void ) {
	uint8_t i;

	/* Configure 2 Arduino pins as outputs for controlling the 4017 reset and clock lines  */
	digitalWrite(HW_4017_RESET_PIN, 0);
	digitalWrite(HW_4017_CLOCK_PIN, 0);
	pinMode(HW_4017_RESET_PIN, OUTPUT);
	pinMode(HW_4017_CLOCK_PIN, OUTPUT);

	digitalWrite(HW_4017_RESET_PIN, 1);    // Reset the decade counter 
	digitalWrite(HW_4017_CLOCK_PIN, 0);    // Lower the clock line

	/* Set all servos at their midpoints              */
	for( i=0 ; i < _4017_NB_CHANNELS ; i++ )
		servo_widths[i] = SYS_TICS_OF_USEC(1500); // SetServo(i,1500);        

	// ----------------------------------------------------------------------------------------- 
	// Configure Timer 1 and setup the Output Compare registers...

	/* Timer1 @ Clk/1: System clock */
	TCCR1A = 0x00;
	TCCR1B = _BV(CS10);

	SERVO_OCR = 0x7FFF;                  /* Set servos to go off some long time from now   */
	TCCR1A |=  _BV(SERVO_COM0 );         /* Set output compare to toggle the output bits   */

#ifdef SERVOS_FALLING_EDGE
	/* Starts CLOCK high for the falling edge case    */
	FORCE_REG |= _BV(SERVO_FORCE);
	// Serial.println("Falling Edge Active!");
#endif

	/* Clear the interrupt flags in case they are set */
	TIMER_IFR = _BV(SERVO_FLAG);

	digitalWrite(HW_4017_RESET_PIN, 0);    // Lower the decade counter reset line to start it running 

	/* Enable our output compare interrupts */
	TIMER_SK |= _BV(SERVO_ENABLE);
	Serial.println("finish1");
}
ISR( TIMER1_COMPA_vect )
{
	static uint8_t servo = 0;
	uint16_t width;

#ifdef SERVOS_FALLING_EDGE
#define RESET_WIDTH SYS_TICS_OF_USEC(1000)
#define FIRST_PULSE_WIDTH SYS_TICS_OF_USEC(100)
	if (servo == _4017_NB_CHANNELS) {
		sbi( _4017_RESET_PORT, _4017_RESET_PIN );    // set Reset pin high

		/** Start a long 1ms reset, keep clock low */
		SERVO_OCR += RESET_WIDTH;
		servo++;
		return;
	}

	if (servo > _4017_NB_CHANNELS) {
		/** Clear the reset, the clock has been toggled high */
		cbi( _4017_RESET_PORT, _4017_RESET_PIN );    // clear reset pin

		/** Start a short pulse-like period */
		SERVO_OCR += FIRST_PULSE_WIDTH;
		servo = 0;   /* Starts a new sequence of pulses next time */
		return;
	}

#else
	if (servo >= _4017_NB_CHANNELS) {
		sbi( _4017_RESET_PORT, _4017_RESET_PIN );     // set reset pin High
		servo = 0;
		// FIXME: 500 ns required by 4017 reset ???? why does it work without!
		//asm( "nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;" );

		cbi( _4017_RESET_PORT, _4017_RESET_PIN );   // clear reset pin
	}
#endif

	width = servo_widths[servo];
	SERVO_OCR += width;
	FORCE_REG |= _BV(SERVO_FORCE);
	servo++;

}

void Servo_4017_init( void );
void Servo_4017_Set_Pulse_Width( int ServoNum, int pulseWidth );

// --------------------------------------------------------------------------------------------------------------------------------------------
/* Global Variable definitions */

uint16_t sWidth[8], sInc[8];

unsigned long myTimer = 0;     // general purpose timer 
unsigned long OneSecTimer = 0;

int LED_On = 0;

LiquidCrystal lcd(12);
char keypressed = 0;
int keyboardPin = 0; // Analog input pin that the keypad is attached to
int keyboardValue = 0;  // value read from the keyboard

int numCount = 0;
char pincode[4];
int state;

void setup(){
	Serial.begin(9600); //hardware serial to PC
	// setup LCD number of columns ans rows
	lcd.begin(16, 2);
	// print message on LCd
	lcd.print("Enter the pin:");
	lcd.setCursor(0,1);    

	// servos
	int n;
	Serial.begin(9600);     // debug output over serial line
	pinMode(ledPin, OUTPUT);
	digitalWrite(ledPin, ON);
	LED_On = 1;
	delay(OneSecond);

	Serial.println("---");
	Serial.println("Arduino 4017 Servo Driver v1.0");
	delay(OneSecond);
	digitalWrite(ledPin, OFF);

	for (n=0; n<8; n++)   // Set all servos to their center positions.
	{
		sWidth[n] = 1500;
		sInc[n] = 3;  // setup each servo to move at a different speed
	}
	sInc[0] = 2;
	Servo_4017_init();	/* Init Timer1 and setup Output Compare interrupt */

	digitalWrite(ledPin, ON);
	OneSecTimer = millis();
	myTimer = millis();
}

void precision_loop ()
{
	int n;
	if ((millis() - myTimer) >= 20)  // 100ms is arbitrary interval for demo
	{
		myTimer = millis();

		for (n=0; n<8; n++)   // Keep servo 0 at center position - move all the rest.  Demos NO jitter on Servo 0. 
		{
			sWidth[n] += sInc[n];
			Servo_4017_Set_Pulse_Width(n, sWidth[n]);
			if ((sWidth[n] > 2100) || (sWidth[n] < 900))  // reverse direction at end of travel
				sInc[n] = -sInc[n];
		}
	}

	if ((millis() - OneSecTimer) >= OneSecond)	  // this goes off once per second
	{
		OneSecTimer = millis();
		LED_On = !LED_On;
		digitalWrite(ledPin, LED_On);					
	}
}

void loop(){
	// keypad start
	keyboardValue = analogRead(keyboardPin); 
	while (keyboardValue < 25){
		keyboardValue = analogRead(keyboardPin);
	}
	readkeyboard(); 
	// keypad end
	precision_loop();
}

void LcdClearLine(int r)
{
	lcd.setCursor(0, r);
	for (int ii = 0; ii < 16; ii = ii + 1) {
		lcd.print(" ");
	}
}

//read the keyboard routine
void readkeyboard(){
	keyboardValue = analogRead(keyboardPin); // read the value (0-1023)
	if (keyboardValue <25){keypressed = 0;}
	if ((keyboardValue >25) && (keyboardValue < 67)){keypressed = '1';}
	if ((keyboardValue >67) && (keyboardValue < 108)){keypressed = '2';}
	if ((keyboardValue >108) && (keyboardValue < 162)){keypressed = '3';}
	if ((keyboardValue >162) && (keyboardValue < 253)){keypressed = '4';}
	if ((keyboardValue >253) && (keyboardValue < 361)){keypressed = '5';}
	if ((keyboardValue >361) && (keyboardValue < 479)){keypressed = '6';}
	if ((keyboardValue >479) && (keyboardValue < 619)){keypressed = '7';}
	if ((keyboardValue >619) && (keyboardValue < 765)){keypressed = '8';}
	if ((keyboardValue >765) && (keyboardValue < 819)){keypressed = '9';}
	if ((keyboardValue >819) && (keyboardValue < 889)){keypressed = '*';}
	if ((keyboardValue >889) && (keyboardValue < 938)){keypressed = '0';}
	if (keyboardValue >938){keypressed = '#';}
	//NOTE: the values used above are all halfway between the value obtained with each keypress in previous test sketch
	while (keyboardValue > 25) {
		//delay (100);
		keyboardValue = analogRead(keyboardPin); // read the value (0-1023)
	}//wait until key no longer being pressed before continuing
	switch (keypressed) {
	case '#':
		Serial.println("ENTER");
		LcdClearLine(0);
		lcd.setCursor(0, 0);
		lcd.print("Welcome");
		lcd.setCursor(0, 1);
		LcdClearLine(1);          
		// send pin to server to validate
		break;
	case '*':
		Serial.println("RESET");
		// clean entered pincode
		numCount = 0;
		//pincode = char[4];
		LcdClearLine(0);
		lcd.setCursor(0, 0);
		lcd.print("Enter the pin:");
		LcdClearLine(1);
		lcd.setCursor(0, 1);
		break;
	default:
		//if(numCount != 4){
		pincode[numCount] = (char) keypressed;
		Serial.println("NUM");
		lcd.write(keypressed);
		//OpenServo(keypressed- '0');
		numCount++;
		//}
	}

	Serial.println(keypressed);  // print the value back to the Serial view window on your PC
	// delay(1000);  // wait 1000 milliseconds before the next loop
}
//end of read the keyboard routine

What is SYS_TICS_OF_USEC(us) supposed to do ?

Why is it not a simple function ?

What is precision_loop() supposed to do ?
Why does a loop need precision ?
Why not just rely on the standard loop() function ?

I see this line

keyboardValue = analogRead(keyboardPin);

in at least three four places. It would make a lot more sense to read the value once and use that everywhere. As it is the value you act on may not be within the bounds you want it to be.

My overall impression is that the code is more complicated than necessary.

...R

Ok, I reduce my code, remove extra lines.

#include <SPI.h>
#include <LiquidCrystal.h>
#include<Servo.h>

LiquidCrystal lcd(12);
Servo servo;
char keypressed = 0;
int keyboardPin = 0; // Analog input pin that the keypad is attached to
int keyboardValue = 0;  // value read from the keyboard

int numCount = 0;
char pincode[4];

void setup(){
	Serial.begin(9600); //hardware serial to PC
	// setup LCD number of columns ans rows
	lcd.begin(16, 2);
	lcd.print("Enter the pin:");
	lcd.setCursor(0,1);   
        servo.attach(10);
        servo.write(0);
}

void loop(){
	// keypad start
	//keyboardValue = analogRead(keyboardPin); 
	while (keyboardValue < 25){
		keyboardValue = analogRead(keyboardPin);
	}
	readkeyboard(); 
	}

void LcdClearLine(int r)
{
	lcd.setCursor(0, r);
	for (int ii = 0; ii < 16; ii = ii + 1) {
		lcd.print(" ");
	}
}

//read the keyboard routine
void readkeyboard(){
	keyboardValue = analogRead(keyboardPin); // read the value (0-1023)
	if (keyboardValue <25){keypressed = 0;}
	if ((keyboardValue >25) && (keyboardValue < 67)){keypressed = '1';}
	if ((keyboardValue >67) && (keyboardValue < 108)){keypressed = '2';}
	if ((keyboardValue >108) && (keyboardValue < 162)){keypressed = '3';}
	if ((keyboardValue >162) && (keyboardValue < 253)){keypressed = '4';}
	if ((keyboardValue >253) && (keyboardValue < 361)){keypressed = '5';}
	if ((keyboardValue >361) && (keyboardValue < 479)){keypressed = '6';}
	if ((keyboardValue >479) && (keyboardValue < 619)){keypressed = '7';}
	if ((keyboardValue >619) && (keyboardValue < 765)){keypressed = '8';}
	if ((keyboardValue >765) && (keyboardValue < 819)){keypressed = '9';}
	if ((keyboardValue >819) && (keyboardValue < 889)){keypressed = '*';}
	if ((keyboardValue >889) && (keyboardValue < 938)){keypressed = '0';}
	if (keyboardValue >938){keypressed = '#';}
	//NOTE: the values used above are all halfway between the value obtained with each keypress in previous test sketch
	while (keyboardValue > 25) {
		//delay (100);
		keyboardValue = analogRead(keyboardPin); // read the value (0-1023)
	}//wait until key no longer being pressed before continuing
	switch (keypressed) {
	case '#':
		//Serial.println("ENTER");
		LcdClearLine(0);
		lcd.setCursor(0, 0);
		lcd.print("Welcome");
		lcd.setCursor(0, 1);
		LcdClearLine(1);          
		// send pin to server to validate
		break;
	case '*':
		numCount = 0;
		LcdClearLine(0);
		lcd.setCursor(0, 0);
		lcd.print("Enter the pin:");
		LcdClearLine(1);
		lcd.setCursor(0, 1);
		break;
	default:
		pincode[numCount] = (char) keypressed;
		Serial.println("NUM");
		lcd.write(keypressed);
		numCount++;
			}
	Serial.println(keypressed);  
	}

Demo: demo
Now all servos are closed all the time. And this is the moment of truth: how I can change angle for only curtain one? :slight_smile:

I haven't read the code, just scrolled through #14, so you're probably wondering why I feel qualified to comment. Anyways, read on...

Have you considered isolating the problem to it's bare minimum ?

As in remove all other clutter and functionality until you have a bare bones representation of what you need to achieve and can say something like "all I want to happen is when X is Y that K does U", and all there is in the program is X,Y,K,U. This is opposed to "here I have ABCDARQ%^!KAAJHIG, and I want it to ~#@ and TY^, but I'm not sure about why KUI(* does %^TRD sometimes, is that correct? or should 4efE sometimes, I'm a noob, help"

This will help in two regards:

  • You might just find the error was related to some of the clutter (conflicting libraries, code error etc.)
  • People on this forum will be much (mu****ch__!) more inclined to both look at your code and here's the kicker: SOLVE it

Forget the LCD
Forget the keypad

Test your Servo mux/demux thingy with hardcoded TEST inputs

Solve that.

Move onto LCD and keypad
TEST that, make sure that the output of that is represented as the same variable type as the input to the servo stuff

THEN, integrate the two...

For anything non-trivial that's how I do it.

Good luck.

Have you considered using a device already designed for this purpose, removes the processing requirements off the Arduino, already on a circuit board, and has a working library?

Just a thought...

happyBanshee:
Ok, I reduce my code, remove extra lines.

You have produced a new program but you have not told us what it does and what you want it to do. Have you tried to make it control a single servo ?

There is an enormous amount of common sense in the advice @1:1 has given in Reply #15.

Get each part of your problem sorted out on its own with the shortest possible program. When all the parts work, then you can start joining them together. That's why I posted the link to planning and implementing a program in Reply #7

Also, please don't ignore comments and questions that people make in an attempt to help you.

...R