"Too many arguments" error - arduino

I am building a laser that is to be controlled by a joystick. The joystick uses 2 servo motors to move the laser in the direction I want. I am using an arduino board that uses C++ coding.
I get a "too many arguments" error on my outputs.
#include <Servo.h>
const int servo1 = 11; // first servo
const int servo2 = 10; // second servo
const int joy1 = 5; // switch 1
const int joy2 = 4; // switch 2
const int joy3 = 3; // switch 3
const int joy4 = 2; // switch 4
int servoVal; // variable to read the value from the digital pin
Servo myservo1; // create servo object to control a servo
Servo myservo2; // create servo object to control a servo
void setup() {
// Servo
myservo1.attach(servo1); // attaches the servo
myservo2.attach(servo2); // attaches the servo
// Inizialize Serial
Serial.begin(9600);
}
void loop(){
// Display Joystick values using the serial monitor
outputJoystick();
// Read the horizontal joystick value (value between 0 and 180)
servoVal = digitalRead(joy1, joy2, joy3, joy4);
servoVal = map(servoVal, 0, 45, 135, 180); // scale it to use it with the servo (result between 0 and 180)
myservo2.write(servoVal); // sets the servo position according to the scaled value
// Read the horizontal joystick value (value between 0 and 180)
servoVal = digitalRead(joy1, joy2, joy3, joy4);
servoVal = map(servoVal, 0, 45, 135, 180); // scale it to use it with the servo (result between 0 and 180)
myservo1.write(servoVal); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
/**
* Display joystick values
*/
void outputJoystick(){
Serial.print(digitalRead(joy1, joy2, joy3, joy4));
Serial.print ("---");
Serial.print(digitalRead(joy1, joy2, joy3, joy4));
Serial.println ("----------------");
}

Would the joystick actually give a digital value or should have been an analogRead? Also I'm pretty sure you can only sample one item at a time with the digitalRead.

Related

How to decrease the set temperature

I've been following this tutorial to create an Arduino PID Temperature Controller.
I can increase the set temperature by rotating the rotary encoder clockwise however I can't decrease the set temperature even when I rotate the encoder anticlockwise. Can someone help explain what I'm doing wrong :)
EDIT: the enconder works fine, I've tested it seperately but this code doesn't work. Thanks
The code is:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <PIDController.h>
#include "max6675.h"
// Define Rotary Encoder Pins
#define CLK_PIN 3
#define DATA_PIN 4
#define SW_PIN 2
// MAX6675 Pins
#define thermoDO 8
#define thermoCS 9
#define thermoCLK 10
// Mosfet Pin
#define mosfet_pin 11
// Serial Enable
#define __DEBUG__
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
/*In this section we have defined the gain values for the
* proportional, integral, and derivative controller I have set
* the gain values with the help of trial and error methods.
*/
#define __Kp 30 // Proportional constant
#define __Ki 0.7 // Integral Constant
#define __Kd 200 // Derivative Constant
int clockPin; // Placeholder por pin status used by the rotary encoder
int clockPinState; // Placeholder por pin status used by the rotary encoder
int set_temperature = 1; // This set_temperature value will increas or decreas if when the rotarty encoder is turned
float temperature_value_c = 0.0; // stores temperature value
long debounce = 0; // Debounce delay
int encoder_btn_count = 0; // used to check encoder button press
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO); // Create an instance for the MAX6675 Sensor Called "thermocouple"
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);// Create an instance for the SSD1306 128X64 OLED "display"
PIDController pid; // Create an instance of the PID controller class, called "pid"
void setup() {
#ifdef __DEBUG__
Serial.begin(9600);
#endif
pinMode(mosfet_pin, OUTPUT); // MOSFET output PIN
pinMode(CLK_PIN, INPUT); // Encoer Clock Pin
pinMode(DATA_PIN, INPUT); //Encoder Data Pin
pinMode(SW_PIN, INPUT_PULLUP);// Encoder SW Pin
pid.begin(); // initialize the PID instance
pid.setpoint(150); // The "goal" the PID controller tries to "reach"
pid.tune(__Kp, __Ki,__Kd); // Tune the PID, arguments: kP, kI, kD
pid.limit(0, 255); // Limit the PID output between 0 and 255, this is important to get rid of integral windup!
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
#ifdef __DEBUG__
Serial.println(F("SSD1306 allocation failed"));
#endif
for (;;); // Don't proceed, loop forever
}
//
display.setRotation(2); //Rotate the Display
display.display(); //Show initial display buffer contents on the screen -- the library initializes this with an Adafruit splash screen.
display.clearDisplay(); // Cleear the Display
display.setTextSize(2); // Set text Size
display.setTextColor(WHITE); // set LCD Colour
display.setCursor(48, 0); // Set Cursor Position
display.println("PID"); // Print the this Text
display.setCursor(0, 20); // Set Cursor Position
display.println("Temperatur"); // Print the this Text
display.setCursor(22, 40); // Set Cursor Position
display.println("Control"); // Print the this Text
display.display(); // Update the Display
delay(2000); // Delay of 200 ms
}
void set_temp()
{
if (encoder_btn_count == 2) // check if the button is pressed twice and its in temperature set mode.
{
display.clearDisplay(); // clear the display
display.setTextSize(2); // Set text Size
display.setCursor(16, 0); // set the diplay cursor
display.print("Set Temp."); // Print Set Temp. on the display
display.setCursor(45, 25); // set the cursor
display.print(set_temperature);// print the set temperature value on the display
display.display(); // Update the Display
}
}
void read_encoder() // In this function we read the encoder data and increment the counter if its rotaing clockwise and decrement the counter if its rotating counter clockwis
{
clockPin = digitalRead(CLK_PIN); // we read the clock pin of the rotary encoder
if (clockPin != clockPinState && clockPin == 1) { // if this condition is true then the encoder is rotaing counter clockwise and we decremetn the counter
if (digitalRead(DATA_PIN) != clockPin) set_temperature = set_temperature - 3; // decrmetn the counter.
else set_temperature = set_temperature + 3; // Encoder is rotating CW so increment
if (set_temperature < 1 )set_temperature = 1; // if the counter value is less than 1 the set it back to 1
if (set_temperature > 150 ) set_temperature = 150; //if the counter value is grater than 150 then set it back to 150
#ifdef __DEBUG__
Serial.println(set_temperature); // print the set temperature value on the serial monitor window
#endif
}
clockPinState = clockPin; // Remember last CLK_PIN state
if ( digitalRead(SW_PIN) == LOW) //If we detect LOW signal, button is pressed
{
if ( millis() - debounce > 80) { //debounce delay
encoder_btn_count++; // Increment the values
if (encoder_btn_count > 2) encoder_btn_count = 1;
#ifdef __DEBUG__
Serial.println(encoder_btn_count);
#endif
}
debounce = millis(); // update the time variable
}
}
void loop()
{
read_encoder(); //Call The Read Encoder Function
set_temp(); // Call the Set Temperature Function
if (encoder_btn_count == 1) // check if the button is pressed and its in Free Running Mode -- in this mode the arduino continiously updates the screen and adjusts the PWM output according to the temperature.
{
temperature_value_c = thermocouple.readCelsius(); // Read the Temperature using the readCelsius methode from MAX6675 Library.
int output = pid.compute(temperature_value_c); // Let the PID compute the value, returns the optimal output
analogWrite(mosfet_pin, output); // Write the output to the output pin
pid.setpoint(set_temperature); // Use the setpoint methode of the PID library to
display.clearDisplay(); // Clear the display
display.setTextSize(2); // Set text Size
display.setCursor(16, 0); // Set the Display Cursor
display.print("Cur Temp."); //Print to the Display
display.setCursor(45, 25);// Set the Display Cursor
display.print(temperature_value_c); // Print the Temperature value to the display in celcius
display.display(); // Update the Display
#ifdef __DEBUG__
Serial.print(temperature_value_c); // Print the Temperature value in *C on serial monitor
Serial.print(" "); // Print an Empty Space
Serial.println(output); // Print the Calculate Output value in the serial monitor.
#endif
delay(200); // Wait 200ms to update the OLED dispaly.
}
}
If you can increment the set temperature it means that the statement
(clockPin != clockPinState && clockPin == 1)
is true and:
(digitalRead(DATA_PIN) != clockPin)
is false. So if you rotate the enconder anticlockwise you should guarantee that
(clockPin != clockPinState && clockPin == 1)
is still true and
(digitalRead(DATA_PIN) != clockPin)
is true.
Perhaps this is a little bit obvious but you can start debugging there. Sorry if my english is not clear.

Incorporating button into Servo Loop

I am extremely new so please bare with me. I am attempting to control a servo by both the internal timer and by button. Essentially the servo will open a door for 6 seconds every 24 hours or so OR if you press the button enter image description here
The loop for the timer works but the button doesn't. However if i just upload the button code it works fine. Help please! Even better if the servo could go to 180 when the button is held down and return to 0 when released would be ideal.
Here is my code. Tell me where I messed up please!
#include <Servo.h>
Servo myservo;
const int BUTTON_PIN = 8;
const int SERVO_PIN = 9;
int angle = 0; // the current angle of servo motor
int lastButtonState; // the previous state of button
int currentButtonState; // the current state of button
void setup(){
myservo.attach(SERVO_PIN);
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
myservo.write(angle);
currentButtonState = digitalRead(BUTTON_PIN);
}
void loop(){
myservo.write(0);// move servos to center position -> 90°
delay(18000);
myservo.write(180);// move servos to center position -> 120°
delay (6000);
lastButtonState = currentButtonState; // save the last state
currentButtonState = digitalRead(BUTTON_PIN); // read new state
if(lastButtonState == HIGH && currentButtonState == LOW) {
Serial.println("The button is pressed");
// change angle of servo motor
if(angle == 180)
angle = 0;
else
if(angle == 0)
angle = 180;
// control servo motor arccoding to the angle
myservo.write(angle);
}
}
Based on your picture your pins should be 7 and 9. Basically, the only issue with your code is that you can not use delay if you also want to be monitoring something (your button). So instead you use what is called a watchdog timer, where you basically make something happen ever so often based on the system clock, but then also remain available to do other things when that is not happening.
Comparing the blink and blink without delay examples in the arduino example sketch folder may help explain this concept further.
#include <Servo.h>
Servo myservo;
const int BUTTON_PIN = 7;
const int SERVO_PIN = 9;
unsigned long dayTimer_ms = 0;
unsigned long autoOpenDelay_ms = 86400000;
int angle = 0;
void setup(){
myservo.attach(SERVO_PIN);
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
myservo.write(0);
}
void loop() {
if(millis() - dayTimer_ms > autoOpenDelay_ms )
{
dayTimer_ms = millis();
myservo.write(180); //(open?)
delay(6000);
myservo.write(0);
}
if(millis()<dayTimer_ms)//overflow handling (in case this runs for more than 50 days straight)
{
dayTimer_ms = millis();
}
if (!digitalRead(BUTTON_PIN) && angle != 180)
{
angle = 180;
myservo.write(angle);
}
if (digitalRead(BUTTON_PIN) && angle != 0)
{
angle = 0;
myservo.write(angle);
}
}

How to make 2 touch sensors move one servo?

I want to make 2 touch sensors do the same thing which is to move the servo.
If either touch sensor is touched the motor moves up or down depending on it's previous position.
The second touch sensor should be named TOUCH_SENSOR_PIN2
here is the code:
#include <Servo.h>
const int TOUCH_SENSOR_PIN = 6; // Arduino pin connected to touch sensor's pin
const int SERVO_PIN = 9; // Arduino pin connected to servo motor's pin
Servo servo; // create servo object to control a servo
// variables will change:
int angle = 141; // the current angle of servo motor
int lastTouchState; // the previous state of touch sensor
int currentTouchState; // the current state of touch sensor
void setup() {
Serial.begin(9600); // initialize serial
pinMode(TOUCH_SENSOR_PIN, INPUT);
servo.attach(SERVO_PIN); // attaches the servo on pin 9 to the servo object
servo.write(angle);
currentTouchState = digitalRead(TOUCH_SENSOR_PIN);
}
void loop() {
lastTouchState = currentTouchState; // save the last state
currentTouchState = digitalRead(TOUCH_SENSOR_PIN); //read new state
if(lastTouchState == LOW && currentTouchState == HIGH) {
// change angle of servo motor
if(angle == 141)
angle = 156;
else
if(angle == 156)
angle = 141;
// control servo motor arccoding to the angle
servo.write(angle);
}
}
I haven't tried it, but this should work. Please replace <pin number> with the number of the pin to which your second touch sensor is connected.
#include <Servo.h>
const int TOUCH_SENSOR_PIN = 6; // Arduino pin connected to touch sensor's pin
const int TOUCH_SENSOR_PIN2 = <pin number>;
const int SERVO_PIN = 9; // Arduino pin connected to servo motor's pin
Servo servo; // create servo object to control a servo
// variables will change:
int angle = 141; // the current angle of servo motor
int lastTouchState; // the previous state of touch sensor
int currentTouchState; // the current state of touch sensor
int lastTouchState2; // the previous state of touch sensor 2
int currentTouchState2; // the current state of touch sensor 2
void setup() {
Serial.begin(9600); // initialize serial
pinMode(TOUCH_SENSOR_PIN, INPUT);
pinMode(TOUCH_SENSOR_PIN2, INPUT);
servo.attach(SERVO_PIN); // attaches the servo on pin 9 to the servo object
servo.write(angle);
currentTouchState = digitalRead(TOUCH_SENSOR_PIN);
currentTouchState2 = digitalRead(TOUCH_SENSOR_PIN2);
}
void loop() {
lastTouchState = currentTouchState; // save the last state
currentTouchState = digitalRead(TOUCH_SENSOR_PIN); //read new state
lastTouchState2 = currentTouchState2; // save the last state
currentTouchState2 = digitalRead(TOUCH_SENSOR_PIN2); //read new state
if((lastTouchState == LOW && currentTouchState == HIGH) || (lastTouchState2 == LOW && currentTouchState2 == HIGH)) {
// change angle of servo motor
if(angle == 141)
angle = 156;
else
if(angle == 156)
angle = 141;
// control servo motor arccoding to the angle
servo.write(angle);
}
}

My Servo is Not Moving, Only When Trying Write 180 degrees

My servo only starts to "change" (that is what the code tells me anyway) when it is set for 180 degrees.
I've tried searching the website as well as Google, but this seems to be something that has to do very specifically with writing to Servo in an advanced non-repeatable kind of way.
The code that changes the servo is:
#include <SoftwareSerial.h>
#include <Servo.h>
const int rxPin = 12;
const int txPin = 13;
SoftwareSerial bluetooth (rxPin, txPin);
Servo myServo;
boolean canMove = true;
int rotation = 0;
int currentRotation = 0;
void setup() {
Serial.begin(9600); // Begins Serial communication
bluetooth.begin(9600);
myServo.attach(11); // Sets a servo on pin 11
}
void loop() {
// put your main code here, to run repeatedly:
// Checks if Serial has something to read
if (bluetooth.available() > 0) {
rotation = bluetooth.read(); // Reads it and sets it to an integer
}
currentRotation = myServo.read();
if (currentRotation != rotation) {
Serial.println("Current Rotation:");
Serial.println(currentRotation);
Serial.println("Set to:");
Serial.println(rotation);
for (int i = currentRotation; i < rotation; i++) {
Serial.println("Writing to servo");
myServo.write(i);
}
}
}
There is a Processing program that sends the data to the Arduino, but I can perfectly see that the numbers are coming in in the Arduino's Serial Monitor (they vary from 0 to 180)
After doing this the only thing that shows up in the Serial Monitor is:
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
over and over. The servo just twitches back and forth. The only time it changes (the number to set to comes from the Processing program) is when the number it is set to be 180. Then it moves even more back and forth and says:
Current Rotation:
179
Set to:
180
Writing to servo
Current Rotation:
179
Set to:
180
Writing to servo
over and over. What is going on and how can I fix it? Cheers, and thanks for the help!
There are some problems with your code:
You don't need to read current servo value, just save the last gave value.
Moving a servo step by step is not a good option as it may have some error for movement. You need to find a dynamic delay based on a threshold of movement. For example, suppose that your max delay time for the servo to fully move from 0 to 180 is 2 seconds, so if you need to move the servo for 90 degrees you need 1 second delay.
You just need to move your servo when a new data came so set servo when new data comes.
Remember to set max_delay based on your servo.
#include <SoftwareSerial.h>
#include <Servo.h>
const int rxPin = 12;
const int txPin = 13;
SoftwareSerial bluetooth(rxPin, txPin);
Servo myServo;
boolean canMove = true;
int rotation = 0;
int currentRotation = 0;
// how much time takes servo to move
int move_delay = 0;
// maximum time for changing servo state from lowest to highest value
const int max_delay = 2;
void setup()
{
Serial.begin(9600); // Begins Serial communication
bluetooth.begin(9600);
myServo.attach(11); // Sets a servo on pin 11
}
void loop()
{
// put your main code here, to run repeatedly:
// Checks if Serial has something to read
if (bluetooth.available() > 0)
{
rotation = bluetooth.read(); // Reads it and sets it to an integer
Serial.print("New value: ");
Serial.println(rotation);
Serial.print("Current Rotation: ");
Serial.println(rotation);
if (currentRotation != rotation)
{
Serial.println("Setting new value");
// find a proper delay
move_delay = (max_delay / 180) * (abs(rotation - currentRotation)) * 1000;
myServo.write(rotation);
delay(move_delay);
currentRotation = rotation;
}
}
}

Arduino - combine sketches

New to programming and Arduino..
I'm currently making a project for my son's Gold Rush diorama with added electronics. From my understanding, it does not like reading delay() codes.
Please, any suggestions are appreciated. Thank you.
I'm trying to combine two sketches;
One that has random fluctuating LEDS (acts as the lanterns in the mine shafts)
The other, a servo that pulls a string up and down (acts as an elevator pulley)
Each sketch alone works properly. I'm not sure the proper way to combine the two without using "delay()"
Leds sketch below;
/*random fluctuating leds*/
void setup() {
// put your setup code here, to run once:
pinMode(12,LOW);
pinMode(11,LOW);
pinMode(10,LOW);
}
void loop() {
// put your main code here, to run repeatedly:
analogWrite(12, random(120)+135);
analogWrite(11, random(120)+135);
analogWrite(10, random(120)+135);
delay(random(100));
}
Servo Sweep Sketch below;
/* Sweep
by BARRAGAN <http://barraganstudio.com>
This example code is in the public domain.
modified 8 Nov 2013
by Scott Fitzgerald
http://arduino.cc/en/Tutorial/Sweep
*/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
In general you can replace delay(1000) with the following code:
unsigned long interval=1000; // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.
void setup() {
//...
}
void loop() {
if ((unsigned long)(millis() - previousMillis) >= interval) {
previousMillis = millis();
// ...
}
}
So you need something like the following code, that I have not tested, but hopefully gives you a starting point:
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
int pos_direction=0; // motor direction
unsigned long interval=1000; // the time we need to wait (analogwrite)
unsigned long previousMillis=0; // millis() returns an unsigned long.
unsigned long interval1=15; // the time we need to wait (servo)
unsigned long previousMillis1=0; // millis() returns an unsigned long.
void setup() {
interval = random(100);
pinMode(12,LOW);
pinMode(11,LOW);
pinMode(10,LOW);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
if ((unsigned long)(millis() - previousMillis) >= interval) {
previousMillis = millis();
analogWrite(12, random(120)+135);
analogWrite(11, random(120)+135);
analogWrite(10, random(120)+135);
interval = random(100);
}
if ((unsigned long)(millis() - previousMillis1) >= interval1) {
previousMillis1 = millis();
if(pos_direction==0){
if(pos==180) pos_direction=1;
else pos++;
}
else if(pos_direction==1){
if(pos==0) pos_direction=0;
else pos--;
}
myservo.write(pos);
// ...
}
}

Resources