Please, help me. I'm trying to connect the 74HC165 (8-bit input shift register) to Arduino UNO via SPI to check the state of 8 buttons. The response is going to be processe to change variable "controls", but it doesn't work properly.
Here is the code:
#include <SPI.h>
/* Latch contact */
enum { REG_LATCH = 8 };
int speed = 100;
/* Variable to store the Controls state for further transfer */
static uint8_t controls = 0;
void setup()
{
/* Turn ON the UART */
Serial.begin(9600);
/* Turn On the SPI */
SPI.begin();
pinMode(REG_LATCH, OUTPUT);
digitalWrite(REG_LATCH, HIGH);
}
void loop()
{
/* Storing the previous system state */
static uint8_t previous_input = 00000000;
digitalWrite(REG_LATCH, LOW);
digitalWrite(REG_LATCH, HIGH);
/* Read the inputs from shift register */
uint8_t input = SPI.transfer(0);
/* If anything has ben changed - report to UART */
if (input != previous_input)
{
/* Remebmer changed positions */
uint8_t changed = input ^ previous_input;
/* Remember current state */
previous_input = input;
Serial.println("Buttons State:\t\tControls State:");
/* Run trough all inputs from shift register */
for (int i = 0; i < 8; i++)
{
/* Print the state of currently checked input*/
Serial.print(input & 1);
/* If button is pressed and previously it was not, then */
if ((input & 1) & (changed & 1))
{
/* Highlight the current changes in system */
Serial.print("_");
/* Toggle controls in this position */
controls = controls ^ (1 << i);
}; /*Otherwise do nothing*/
/* Move to next bit of inputs. */
input >>= 1;
changed >>= 1;
};
Serial.print("\t\t");
for (int i = 0; i < 8; i++)
{
/* Print current control */
Serial.print(controls);
controls >>= 1;
}
Serial.println();
}
}
And what it writes to the Serial:
1) After pressing button 1:
Buttons State: Controls State:
1_0000000 10000000
2) When it releases:
Buttons State: Controls State:
00000000 00000000
3) After pressing button 7:
Buttons State: Controls State:
0000001_0 64321684210
4) After its releasing:
Buttons State: Controls State:
00000000 00000000
5) After pressing button 1:
Buttons State: Controls State:
1_0000000 10000000
6) When it releases:
Buttons State: Controls State:
00000000 00000000
How it supposed to work:
1) After pressing button 1:
Buttons State: Controls State:
1_0000000 10000000
2) After its release:
Buttons State: Controls State:
00000000 10000000
3) After pressing button 7:
Buttons State: Controls State:
0000001_0 10000010
4) After its releasing
Buttons State: Controls State:
00000000 10000010
5) After next pressing of button 1:
Buttons State: Controls State:
1_0000000 00000010
6) After its releasing:
Buttons State: Controls State:
00000000 00000010
Help me, please.
What am I doing wrong?
First check your shift register is connected correctly. The best way of distinguishing hardware issues with software issues is to plug an oscilloscope on the output pin of your shift register.
Your REG_LATCH pin must be plugged to pin1 of your shift register (assuming we are talking about this one http://www.nxp.com/documents/data_sheet/74HC_HCT165.pdf).
The way it works is that you must pull this pin down, transfer data then pull it up. Thus the sequence is rather:
digitalWrite(REG_LATCH, LOW);
/* Read the inputs from shift register */
uint8_t input = SPI.transfer(0);
digitalWrite(REG_LATCH, HIGH);
Then instead of shifting index and changed in your loop, I would have used this:
input & i
changed & i
or
input & (7 - i)
changed & (7 - i)
depending on the order your want to handle your bits.
I've figured out the problem.
I've made a mistake in depicturing of "Controls" state. Togling was working as it was supposed to work.
This is code for proper presenting:
#include <SPI.h>
/* ----------------------------------------------------------------------- */
/* Global System variables */
/* ----------------------------------------------------------------------- */
/* Storing the previous system state */
static uint8_t previous_input = 0;
/* Variable to store the Controls state for further transfer */
static uint8_t controls = 0;
/* ----------------------------------------------------------------------- */
/* Configuration of shift input register 74HC165 */
/* Latch contact */
enum { REG_LATCH = 8 };
/* ----------------------------------------------------------------------- */
void setup()
{
/* Turn ON the UART */
Serial.begin(9600);
/* Turn On the SPI */
SPI.begin();
pinMode(REG_LATCH, OUTPUT);
digitalWrite(REG_LATCH, HIGH);
}
/* ----------------------------------------------------------------------- */
void print_bin_to_serial(int digit){
/* Run trough all inputs from shift register */
for (int i = 0; i < 8; i++)
{
/* Print the state of currently checked input*/
Serial.print(((digit << i) >> 7) & 1);
};
}
/* ----------------------------------------------------------------------- */
void loop()
{
digitalWrite(REG_LATCH, LOW);
digitalWrite(REG_LATCH, HIGH);
/* Read the inputs from shift register */
uint8_t input = SPI.transfer(0);
/* If anything has ben changed - report to UART */
if (input != previous_input)
{
/* Remember changed positions */
uint8_t changed = input ^ previous_input;
/* Remember current state */
previous_input = input;
/* Fixing, what positions had to be switched */
uint8_t items_to_change = (input & changed);
controls ^= items_to_change;
/* Code is just for printing */
Serial.println("Buttons State:\t\tChanged:\t\tItems to change:\tControls State:");
print_bin_to_serial(input);
Serial.print("\t\t");
print_bin_to_serial(changed);
Serial.print("\t\t");
print_bin_to_serial(items_to_change);
Serial.print("\t\t");
print_bin_to_serial(controls);
Serial.println();
};
}
#Tom, thanks for advise. That didn't fix a problem, but helped to make a code shorter.
Related
I am trying to follow a tutorial from youtube on using ROS with Arduino to control motors, and I have connected my L298N with the battery precisely as the video describes and have uploaded sketch 1 with the supporting folder and it loads properly. The Arduino is powered properly via USB, but that connection is not shown in the diagram. When I type the "e" command, I get the proper response of "0 0" and when I do the "o 255 255" it says "OK" and drives properly but upon using "e" to recheck the encoders I am getting the same "0 0". If anyone can spot something wrong with this, I would really appreciate the help in fixing it. Diagram and Code Below
Code:
#define USE_BASE // Enable the base controller code
//#undef USE_BASE // Disable the base controller code
/* Define the motor controller and encoder library you are using */
#ifdef USE_BASE
/* The Pololu VNH5019 dual motor driver shield */
//#define POLOLU_VNH5019
/* The Pololu MC33926 dual motor driver shield */
//#define POLOLU_MC33926
/* The RoboGaia encoder shield */
//#define ROBOGAIA
/* Encoders directly attached to Arduino board */
#define ARDUINO_ENC_COUNTER
/* L298 Motor driver*/
#define L298_MOTOR_DRIVER
#endif
//#define USE_SERVOS // Enable use of PWM servos as defined in servos.h
#undef USE_SERVOS // Disable use of PWM servos
/* Serial port baud rate */
#define BAUDRATE 57600
/* Maximum PWM signal */
#define MAX_PWM 255
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
/* Include definition of serial commands */
#include "commands.h"
/* Sensor functions */
#include "sensors.h"
/* Include servo support if required */
#ifdef USE_SERVOS
#include <Servo.h>
#include "servos.h"
#endif
#ifdef USE_BASE
/* Motor driver function definitions */
#include "motor_driver.h"
/* Encoder driver function definitions */
#include "encoder_driver.h"
/* PID parameters and functions */
#include "diff_controller.h"
/* Run the PID loop at 30 times per second */
#define PID_RATE 30 // Hz
/* Convert the rate into an interval */
const int PID_INTERVAL = 1000 / PID_RATE;
/* Track the next time we make a PID calculation */
unsigned long nextPID = PID_INTERVAL;
/* Stop the robot if it hasn't received a movement command
in this number of milliseconds */
#define AUTO_STOP_INTERVAL 2000
long lastMotorCommand = AUTO_STOP_INTERVAL;
#endif
/* Variable initialization */
// A pair of varibles to help parse serial commands (thanks Fergs)
int arg = 0;
int index = 0;
// Variable to hold an input character
char chr;
// Variable to hold the current single-character command
char cmd;
// Character arrays to hold the first and second arguments
char argv1[16];
char argv2[16];
// The arguments converted to integers
long arg1;
long arg2;
/* Clear the current command parameters */
void resetCommand() {
cmd = NULL;
memset(argv1, 0, sizeof(argv1));
memset(argv2, 0, sizeof(argv2));
arg1 = 0;
arg2 = 0;
arg = 0;
index = 0;
}
/* Run a command. Commands are defined in commands.h */
int runCommand() {
int i = 0;
char *p = argv1;
char *str;
int pid_args[4];
arg1 = atoi(argv1);
arg2 = atoi(argv2);
switch(cmd) {
case GET_BAUDRATE:
Serial.println(BAUDRATE);
break;
case ANALOG_READ:
Serial.println(analogRead(arg1));
break;
case DIGITAL_READ:
Serial.println(digitalRead(arg1));
break;
case ANALOG_WRITE:
analogWrite(arg1, arg2);
Serial.println("OK");
break;
case DIGITAL_WRITE:
if (arg2 == 0) digitalWrite(arg1, LOW);
else if (arg2 == 1) digitalWrite(arg1, HIGH);
Serial.println("OK");
break;
case PIN_MODE:
if (arg2 == 0) pinMode(arg1, INPUT);
else if (arg2 == 1) pinMode(arg1, OUTPUT);
Serial.println("OK");
break;
case PING:
Serial.println(Ping(arg1));
break;
#ifdef USE_SERVOS
case SERVO_WRITE:
servos[arg1].setTargetPosition(arg2);
Serial.println("OK");
break;
case SERVO_READ:
Serial.println(servos[arg1].getServo().read());
break;
#endif
#ifdef USE_BASE
case READ_ENCODERS:
Serial.print(readEncoder(LEFT));
Serial.print(" ");
Serial.println(readEncoder(RIGHT));
break;
case RESET_ENCODERS:
resetEncoders();
resetPID();
Serial.println("OK");
break;
case MOTOR_SPEEDS:
/* Reset the auto stop timer */
lastMotorCommand = millis();
if (arg1 == 0 && arg2 == 0) {
setMotorSpeeds(0, 0);
resetPID();
moving = 0;
}
else moving = 1;
leftPID.TargetTicksPerFrame = arg1;
rightPID.TargetTicksPerFrame = arg2;
Serial.println("OK");
break;
case MOTOR_RAW_PWM:
/* Reset the auto stop timer */
lastMotorCommand = millis();
resetPID();
moving = 0; // Sneaky way to temporarily disable the PID
setMotorSpeeds(arg1, arg2);
Serial.println("OK");
break;
case UPDATE_PID:
while ((str = strtok_r(p, ":", &p)) != '\0') {
pid_args[i] = atoi(str);
i++;
}
Kp = pid_args[0];
Kd = pid_args[1];
Ki = pid_args[2];
Ko = pid_args[3];
Serial.println("OK");
break;
#endif
default:
Serial.println("Invalid Command");
break;
}
}
/* Setup function--runs once at startup. */
void setup() {
Serial.begin(BAUDRATE);
// Initialize the motor controller if used */
#ifdef USE_BASE
#ifdef ARDUINO_ENC_COUNTER
//set as inputs
DDRD &= ~(1<<LEFT_ENC_PIN_A);
DDRD &= ~(1<<LEFT_ENC_PIN_B);
DDRC &= ~(1<<RIGHT_ENC_PIN_A);
DDRC &= ~(1<<RIGHT_ENC_PIN_B);
//enable pull up resistors
PORTD |= (1<<LEFT_ENC_PIN_A);
PORTD |= (1<<LEFT_ENC_PIN_B);
PORTC |= (1<<RIGHT_ENC_PIN_A);
PORTC |= (1<<RIGHT_ENC_PIN_B);
// tell pin change mask to listen to left encoder pins
PCMSK2 |= (1 << LEFT_ENC_PIN_A)|(1 << LEFT_ENC_PIN_B);
// tell pin change mask to listen to right encoder pins
PCMSK1 |= (1 << RIGHT_ENC_PIN_A)|(1 << RIGHT_ENC_PIN_B);
// enable PCINT1 and PCINT2 interrupt in the general interrupt mask
PCICR |= (1 << PCIE1) | (1 << PCIE2);
#endif
initMotorController();
resetPID();
#endif
/* Attach servos if used */
#ifdef USE_SERVOS
int i;
for (i = 0; i < N_SERVOS; i++) {
servos[i].initServo(
servoPins[i],
stepDelay[i],
servoInitPosition[i]);
}
#endif
}
/* Enter the main loop. Read and parse input from the serial port
and run any valid commands. Run a PID calculation at the target
interval and check for auto-stop conditions.
*/
void loop() {
while (Serial.available() > 0) {
// Read the next character
chr = Serial.read();
// Terminate a command with a CR
if (chr == 13) {
if (arg == 1) argv1[index] = NULL;
else if (arg == 2) argv2[index] = NULL;
runCommand();
resetCommand();
}
// Use spaces to delimit parts of the command
else if (chr == ' ') {
// Step through the arguments
if (arg == 0) arg = 1;
else if (arg == 1) {
argv1[index] = NULL;
arg = 2;
index = 0;
}
continue;
}
else {
if (arg == 0) {
// The first arg is the single-letter command
cmd = chr;
}
else if (arg == 1) {
// Subsequent arguments can be more than one character
argv1[index] = chr;
index++;
}
else if (arg == 2) {
argv2[index] = chr;
index++;
}
}
}
// If we are using base control, run a PID calculation at the appropriate intervals
#ifdef USE_BASE
if (millis() > nextPID) {
updatePID();
nextPID += PID_INTERVAL;
}
// Check to see if we have exceeded the auto-stop interval
if ((millis() - lastMotorCommand) > AUTO_STOP_INTERVAL) {;
setMotorSpeeds(0, 0);
moving = 0;
}
#endif
// Sweep servos
#ifdef USE_SERVOS
int i;
for (i = 0; i < N_SERVOS; i++) {
servos[i].doSweep();
}
#endif
}
Encoder Pin Designations:
/* *************************************************************
Encoder driver function definitions - by James Nugen
************************************************************ */
#ifdef ARDUINO_ENC_COUNTER
//below can be changed, but should be PORTD pins;
//otherwise additional changes in the code are required
#define LEFT_ENC_PIN_A PD2 //pin 2
#define LEFT_ENC_PIN_B PD3 //pin 3
//below can be changed, but should be PORTC pins
#define RIGHT_ENC_PIN_A PC4 //pin A4
#define RIGHT_ENC_PIN_B PC5 //pin A5
#endif
long readEncoder(int i);
void resetEncoder(int i);
void resetEncoders();
Encoder Driver:
/* *************************************************************
Encoder definitions
Add an "#ifdef" block to this file to include support for
a particular encoder board or library. Then add the appropriate
#define near the top of the main ROSArduinoBridge.ino file.
************************************************************ */
#ifdef USE_BASE
#ifdef ROBOGAIA
/* The Robogaia Mega Encoder shield */
#include "MegaEncoderCounter.h"
/* Create the encoder shield object */
MegaEncoderCounter encoders = MegaEncoderCounter(4); // Initializes the Mega Encoder Counter in the 4X Count mode
/* Wrap the encoder reading function */
long readEncoder(int i) {
if (i == LEFT) return encoders.YAxisGetCount();
else return encoders.XAxisGetCount();
}
/* Wrap the encoder reset function */
void resetEncoder(int i) {
if (i == LEFT) return encoders.YAxisReset();
else return encoders.XAxisReset();
}
#elif defined(ARDUINO_ENC_COUNTER)
volatile long left_enc_pos = 0L;
volatile long right_enc_pos = 0L;
static const int8_t ENC_STATES [] = {0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,1,0}; //encoder lookup table
/* Interrupt routine for LEFT encoder, taking care of actual counting */
ISR (PCINT2_vect){
static uint8_t enc_last=0;
enc_last <<=2; //shift previous state two places
enc_last |= (PIND & (3 << 2)) >> 2; //read the current state into lowest 2 bits
left_enc_pos += ENC_STATES[(enc_last & 0x0f)];
}
/* Interrupt routine for RIGHT encoder, taking care of actual counting */
ISR (PCINT1_vect){
static uint8_t enc_last=0;
enc_last <<=2; //shift previous state two places
enc_last |= (PINC & (3 << 4)) >> 4; //read the current state into lowest 2 bits
right_enc_pos += ENC_STATES[(enc_last & 0x0f)];
}
/* Wrap the encoder reading function */
long readEncoder(int i) {
if (i == LEFT) return left_enc_pos;
else return right_enc_pos;
}
/* Wrap the encoder reset function */
void resetEncoder(int i) {
if (i == LEFT){
left_enc_pos=0L;
return;
} else {
right_enc_pos=0L;
return;
}
}
#else
#error A encoder driver must be selected!
#endif
/* Wrap the encoder reset function */
void resetEncoders() {
resetEncoder(LEFT);
resetEncoder(RIGHT);
}
#endif
I think if you use a Mega instead of an Uno, the pin ports are different.
So change the port from PD4 to PE4 and PD3 to PE5. Also, change PC4 to PF4 and PC5 to PF5.
In the Encoder.ino, you also have to change the ports accordingly.
Encoder.h:
#define LEFT_ENC_PIN_A PE4 //pin 2
#define LEFT_ENC_PIN_B PE5 //pin 3
//below can be changed, but should be PORTC pins
#define RIGHT_ENC_PIN_A PF5 //pin A4
#define RIGHT_ENC_PIN_B PF5 //pin A5
Encoder.ino:
/* Interrupt routine for LEFT encoder, taking care of actual counting */
ISR (PCINT2_vect){
static uint8_t enc_last=0;
enc_last <<=2; //shift previous state two places
enc_last |= (PINE & (3 << 2)) >> 2; //read the current state into lowest 2 bits
left_enc_pos += ENC_STATES[(enc_last & 0x0f)];
}
/* Interrupt routine for RIGHT encoder, taking care of actual counting */
ISR (PCINT1_vect){
static uint8_t enc_last=0;
enc_last <<=2; //shift previous state two places
enc_last |= (PINF & (3 << 4)) >> 4; //read the current state into lowest 2 bits
right_enc_pos += ENC_STATES[(enc_last & 0x0f)];
}
I'm trying Sim800l and ESP8066 As my serial communication to Mega r3.
when i try sim800l code side, something like this: which i refined the code a little bit. In Serial monitor handshakes are ok. but when new sms arrives it doesn't show the right content.
Why with same code I see different results?
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
Serial.println("Starting...");
delay(1000);
Serial1.println("AT");
pollSms();
Serial1.println("AT+CMGF=1");
pollSms();
Serial1.println("AT+CNMI=1,2,0,0,0");
pollSms();
}
void loop()
{
pollSms();
}
void pollSms()
{
delay(500);
while (Serial.available())
{
Serial1.write(Serial.read());
}
while(Serial1.available())
{
Serial.write(Serial1.read());
}
}
everything is just fine but when I try
#include <SPI.h>//Communicate via WiFi
#include <DHT.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <WiFi.h>
/* Libraries */
/* Variables */
char id[] = "id";//id of Wifi network
char pass[] = "password";//password of Wifi network
const char* host = "esp8266sd";
float humadity1 , temprature1=25;//Solon 1
float humadity2 , temprature2;//Solon 2
int Soil_humadity1,Soil_humadity2,Soil_humadity3;
char c;
String WiFi_instruction="";
String SMSmessage="";
String number, Answer;
boolean valid;
#define TWO_HRS 7200000
unsigned long startTime1,startTime2;
/* Variables */
/* AM2301 */
#define DHTTYPE DHT21 // It defines which kind of humadity and temprature sensor is connecter (AM2301)
DHT dht1(DHTPIN1, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);
/* AM2301 */
/* Android App */
WiFiServer server(80);
/* Android App */
/* Valid numbers */
String num1="9016057005";
String num2="9026057005";//change it
/* Valid numbers */
void setup()
{
/* Pins Settings */
/* Serial communications */
Serial.begin(9600); // setup baudrate for transition to "serial monitor"
Serial1.begin(9600);//Sim800l Serial Communication
Serial3.begin(9600);//ESP8266 Serial Communication
/* SMS Settings */
Serial.println("Start!...");
Serial1.println("AT"); //Send AT command it will says "OK" if everything is fine
Serialcom(); //description below
Serial1.println("AT+CMGF=0"); // Configuring TEXT mode
Serialcom();
Serial1.println("AT+IPR=9600");
Serial1.println("AT+CNMI=1,2,0,0,0");
Serialcom();
/* SMS Settings */
/* Serial communications */
/* Timers */
startTime1 = millis();
startTime2 = millis();
/* Timers */
/* Sensors */
dht1.begin(); //setup humadity and temprature sensor: Solon 1
dht2.begin(); //setup humadity and temprature sensor: Solon 2
humadity1 = dht1.readHumidity();
temprature1 = dht1.readTemperature();
humadity2 = dht2.readHumidity();
temprature2 = dht2.readTemperature();
/* Sensors */
}//setup ended
void loop()
{
char x;
/* Receiving instruction from WiFi' serial */
while (Serial3.available())
{
x=Serial3.read();
WiFi_instruction.concat(x);
}
Serial.println("WiFi instructions");
/* Check for any instruction*/
WiFi_instruction="";// WiFi_instruction is empty now.
}//if WiFi_instruction.length()!-0
/* Receiving instruction from WiFi' serial */
/* Yl-69 Sensors */
Soil_humadity1=digitalRead(YL1);//If it return 1, soil is ok otherwise not
Soil_humadity2=digitalRead(YL2);
Soil_humadity3=digitalRead(YL3);
/* Yl-69 Sensors */
/* AS2301 Sensors's Data */
float temp_temprature1,temp_temprature2,temp_humadity1,temp_humadity2;
temp_temprature1= dht1.readTemperature();
temp_temprature2= dht2.readTemperature();
temp_humadity1=dht1.readHumidity();
temp_humadity2=dht2.readHumidity();
//Whether data is NaN or 0 or some none sense increment-decrement, new numbers won't be considered
if(isnan(temp_temprature1) ||isnan(temp_temprature2)||
isnan(temp_humadity1)||isnan(temp_humadity2))
{
/* Do nothing */
}
else
{
if(temp_temprature1!=0 &&
temp_temprature2!=0&&
temp_humadity1!=0 &&
temp_humadity2!=0)
{
if(abs(dht1.readHumidity()-humadity1)<10
&& abs(dht2.readHumidity()-humadity2)<10
&& abs(dht1.readTemperature()-temprature1)<10
&& abs(dht2.readTemperature()-temprature2)<10)
{
Serial.print(" Sensor values have been changed ");
humadity1 = dht1.readHumidity();
temprature1 = dht1.readTemperature();
humadity2 = dht2.readHumidity();
temprature2 = dht2.readTemperature();
}
}
}
/* AS2301 Sensors's Data */
/* Check for any SMS */
while(Serial1.available())
{
x=Serial1.read();
SMSmessage.concat(x);
}
Serial.println("SMS:");
Serial.println(SMSmessage);
if(SMSmessage.length()>0)
{
int valid1=SMSmessage.indexOf(num1);
int valid2=SMSmessage.indexOf(num2);
if(valid1==0 || valid2==0)
{
Serial.println("number is valid");
valid=true;
}
/*Extranct the number to andwer */
if(valid1==0)
number=num1;
if(valid2==0)
number=num2;
/*Extranct the number to andwer */
/*Check for any sms */
/* Answering via SMS */
//If there is the Code for a specific Instruction it return 1 otherwise returns -1
if(valid)
{
inst00=SMSmessage.indexOf(inst0);
inst01_CHECK=SMSinst01=SMSmessage.indexOf(inst1);//automatic
inst02_CHECK=SMSinst02=SMSmessage.indexOf(inst2);
inst03_CHECK=SMSinst03=SMSmessage.indexOf(inst3);
inst04_CHECK=SMSinst04=SMSmessage.indexOf(inst4);
if(SMSinst02 ==-1 && SMSinst03==-1 && SMSinst04==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst01=0;
inst05_CHECK=SMSinst05=SMSmessage.indexOf(inst5);//automatic
inst06_CHECK=SMSinst06=SMSmessage.indexOf(inst6);
inst07_CHECK=SMSinst07=SMSmessage.indexOf(inst7);
inst08_CHECK=SMSinst08=SMSmessage.indexOf(inst8);
if(SMSinst06 ==-1 && SMSinst07==-1 && SMSinst08==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst05=0;
inst09_CHECK=SMSinst09=SMSmessage.indexOf(inst9);//automatic
inst010_CHECK=SMSinst010=SMSmessage.indexOf(inst10);
inst011_CHECK=SMSinst011=SMSmessage.indexOf(inst11);
if(SMSinst010 ==-1 && SMSinst011==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst09=0;
inst012_CHECK=SMSinst012=SMSmessage.indexOf(inst12);//automatic
inst013_CHECK=SMSinst013=SMSmessage.indexOf(inst13);
inst014_CHECK=SMSinst014=SMSmessage.indexOf(inst14);
if(SMSinst013 ==-1 && SMSinst014==-1)// if none of the non-automatic in selected it mast remain automatic
inst012=0;
inst015_CHECK=SMSinst015=SMSmessage.indexOf(inst15);//automatic
inst016_CHECK=SMSinst016=SMSmessage.indexOf(inst16);
inst017_CHECK=SMSinst017=SMSmessage.indexOf(inst17);
if(SMSinst016 ==-1 && SMSinst017==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst015=0;
inst018_CHECK=SMSinst018=SMSmessage.indexOf(inst18);//automatic
inst019_CHECK=SMSinst019=SMSmessage.indexOf(inst19);
inst020_CHECK=SMSinst020=SMSmessage.indexOf(inst20);
if(SMSinst019 ==-1 && SMSinst020==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst018=0;
inst021_CHECK=SMSinst021=SMSmessage.indexOf(inst21);//automatic
inst022_CHECK=SMSinst022=SMSmessage.indexOf(inst22);
inst023_CHECK=SMSinst023=SMSmessage.indexOf(inst23);
if(SMSinst022 ==-1 && SMSinst023==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst021=0;
inst024_CHECK=SMSinst024=SMSmessage.indexOf(inst24);//automatic
inst025_CHECK=SMSinst025=SMSmessage.indexOf(inst25);
inst026_CHECK=SMSinst026=SMSmessage.indexOf(inst26);
if(SMSinst025 ==-1 && SMSinst026==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst024=0;
inst027_CHECK=SMSinst027=SMSmessage.indexOf(inst27);//automatic
inst028_CHECK=SMSinst028=SMSmessage.indexOf(inst28);
inst029_CHECK=SMSinst029=SMSmessage.indexOf(inst29);
if(SMSinst028 ==-1 && SMSinst029==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst027=0;
SMSmessage="";//SMSmessage now is empty until next sms
}//if valid
}// if SMS.length()
Serial.println("SMS instructions");
if(inst00)
{
String statSoil1,statSoil2,statSoil3;
/* YL, Soil's humadity Sensors results */
}//Loop ends
/*Functions */
/*
void Serialcom()
{
delay(500);
while(Serial.available()) // IDE serial l serial Serial1
{
Serial1.write(Serial.read());//Forward what Serial received to Software Serial Port
}
while(Serial1.available()) //serialSerial1 l serial dial IDE
{
Serial.write(Serial1.read());//Forward what Software Serial received to Serial Port
}
}
/*Functions */
I've taken my Arduino out of the box about an hour ago and I'm trying to get some bits of code working.
The code below is supposed to wait for an input from the Serial Monitor and set the LED connected at terminal 9 to the input value.
The Arduino reads the value the first time, but it always sets the LED to full brightness and never prints the "input invalid". The Arduino also doesn't read any value after the first one. What is the reason?
int A;
void setup()
{
Serial.begin(9600);
Serial.println("input value");
}
void loop()
{
A = 0; /* Reset A */
if (Serial.available() > 0) /* Wait for input */
{
A = Serial.read(); /* Read input */
if(A >= 0 && A <= 255) /* Check for valid input */
{
analogWrite(9, A); /* Set value of an LED */
}
else
{
Serial.println("input invalid");
}
}
delay(100); /* Wait 0.1 second */
}
According to the rest of code the Serial.parseInt() should be used instead of reading one character by Serial.read().
I'm trying to control two SPI devices at once using identical MISO, MOSI, and CLOCK pins but different SS pins.
One is the Wifly shield from SparkFun that uses a SPI-to-UART chip, the other is a MAX31855.
They work independently, but not together..
The SPI-to-UART code that I'm using is listed below. The only changes I've made is in the header file; I set select() and deselect() to public.
#include "SpiUart.h"
// See section 8.10 of the datasheet for definitions
// of bits in the Enhanced Features Register (EFR)
#define EFR_ENABLE_CTS 1 << 7
#define EFR_ENABLE_RTS 1 << 6
#define EFR_ENABLE_ENHANCED_FUNCTIONS 1 << 4
// See section 8.4 of the datasheet for definitions
// of bits in the Line Control Register (LCR)
#define LCR_ENABLE_DIVISOR_LATCH 1 << 7
// The original crystal frequency used on the board (~12 MHz) didn't
// give a good range of baud rates so around July 2010 the crystal
// was replaced with a better frequency (~14 MHz).
#ifndef USE_14_MHZ_CRYSTAL
#define USE_14_MHZ_CRYSTAL true // true (14 MHz) , false (12 MHz)
#endif
#if USE_14_MHZ_CRYSTAL
#define XTAL_FREQUENCY 14745600UL // On-board crystal (New mid-2010 Version)
#else
#define XTAL_FREQUENCY 12288000UL // On-board crystal (Original Version)
#endif
// See datasheet section 7.8 for configuring the
// "Programmable baud rate generator"
#define PRESCALER 1 // Default prescaler after reset
#define BAUD_RATE_DIVISOR(baud) ((XTAL_FREQUENCY/PRESCALER)/(baud*16UL))
// TODO: Handle configuration better
// SC16IS750 register values
struct SPI_UART_cfg {
char DataFormat;
char Flow;
};
struct SPI_UART_cfg SPI_Uart_config = {
0x03,
// We need to enable flow control or we overflow buffers and
// lose data when used with the WiFly. Note that flow control
// needs to be enabled on the WiFly for this to work but it's
// possible to do that with flow control enabled here but not there.
// TODO: Make this able to be configured externally?
EFR_ENABLE_CTS | EFR_ENABLE_RTS | EFR_ENABLE_ENHANCED_FUNCTIONS
};
void SpiUartDevice::begin(unsigned long baudrate) {
/*
* Initialize SPI and UART communications
*
* Uses BAUD_RATE_DEFAULT as baudrate if none is given
*/
SPI.begin();
initUart(baudrate);
}
void SpiUartDevice::deselect() {
/*
* Deslects the SPI device
*/
digitalWrite(SS, HIGH);
}
void SpiUartDevice::select() {
/*
* Selects the SPI device
*/
digitalWrite(SS, LOW);
}
void SpiUartDevice::initUart(unsigned long baudrate) {
/*
* Initialise the UART.
*
* If initialisation fails this method does not return.
*/
// Initialise and test SC16IS750
configureUart(baudrate);
if(!uartConnected()){
while(1) {
// Lock up if we fail to initialise SPI UART bridge.
};
}
// The SPI UART bridge is now successfully initialised.
}
void SpiUartDevice::setBaudRate(unsigned long baudrate) {
unsigned long divisor = BAUD_RATE_DIVISOR(baudrate);
writeRegister(LCR, LCR_ENABLE_DIVISOR_LATCH); // "Program baudrate"
writeRegister(DLL, lowByte(divisor));
writeRegister(DLM, highByte(divisor));
}
void SpiUartDevice::configureUart(unsigned long baudrate) {
/*
* Configure the settings of the UART.
*/
// TODO: Improve with use of constants and calculations.
setBaudRate(baudrate);
writeRegister(LCR, 0xBF); // Access EFR register
writeRegister(EFR, SPI_Uart_config.Flow); // Enable enhanced registers
writeRegister(LCR, SPI_Uart_config.DataFormat); // 8 data bit, 1 stop bit, no parity
writeRegister(FCR, 0x06); // Reset TXFIFO, reset RXFIFO, non FIFO mode
writeRegister(FCR, 0x01); // Enable FIFO mode
}
boolean SpiUartDevice::uartConnected() {
/*
* Check that UART is connected and operational.
*/
// Perform read/write test to check if the UART is working
const char TEST_CHARACTER = 'H';
writeRegister(SPR, TEST_CHARACTER);
return (readRegister(SPR) == TEST_CHARACTER);
}
void SpiUartDevice::writeRegister(byte registerAddress, byte data) {
/*
* Write <data> byte to the SC16IS750 register <registerAddress>
*/
select();
SPI.transfer(registerAddress);
SPI.transfer(data);
deselect();
}
byte SpiUartDevice::readRegister(byte registerAddress) {
/*
* Read byte from SC16IS750 register at <registerAddress>.
*/
// Used in SPI read operations to flush slave's shift register
const byte SPI_DUMMY_BYTE = 0xFF;
char result;
select();
SPI.transfer(SPI_READ_MODE_FLAG | registerAddress);
result = SPI.transfer(SPI_DUMMY_BYTE);
deselect();
return result;
}
int SpiUartDevice::available() {
/*
* Get the number of bytes (characters) available for reading.
*
* This is data that's already arrived and stored in the receive
* buffer (which holds 64 bytes).
*/
// This alternative just checks if there's data but doesn't
// return how many characters are in the buffer:
// readRegister(LSR) & 0x01
return readRegister(RXLVL);
}
int SpiUartDevice::read() {
/*
* Read byte from UART.
*
* Returns byte read or or -1 if no data available.
*
* Acts in the same manner as 'Serial.read()'.
*/
if (!available()) {
return -1;
}
return readRegister(RHR);
}
size_t SpiUartDevice::write(byte value) {
/*
* Write byte to UART.
*/
while (readRegister(TXLVL) == 0) {
// Wait for space in TX buffer
};
writeRegister(THR, value);
}
size_t SpiUartDevice::write(const char *str, size_t size) {
/*
* Write string to UART.
*/
while (size--)
write(*str++);
while (readRegister(TXLVL) < 64) {
// Wait for empty TX buffer (slow).
// (But apparently still not slow enough to ensure delivery.)
};
}
void SpiUartDevice::flush() {
/*
* Flush characters from SC16IS750 receive buffer.
*/
// Note: This may not be the most appropriate flush approach.
// It might be better to just flush the UART's buffer
// rather than the buffer of the connected device
// which is essentially what this does.
while(available() > 0) {
read();
}
}
void SpiUartDevice::ioSetDirection(unsigned char bits) {
writeRegister(IODIR, bits);
}
void SpiUartDevice::ioSetState(unsigned char bits) {
writeRegister(IOSTATE, bits);
}
I attempted to use it like this:
SpiSerial.deselect(); //Deselect Wi-Fi
delay(100); //Wait, just for the heck of it.
currentTemp = thermocouple.readFarenheit(); //Read from max31855... readFarenheit selects and unselects its own SS pin.
SpiSerial.select(); //Reselect Wi-Fi
But it's still unable to function. What further things should I attempt in order to get this to function?
TWO issues:
You don't mention anything about the MAX31855 library or how it is used. It looks like you are using Adafruit_MAX31855. Did you set the second argument of the constructors instance to "SS" or the value of the pin for chip select tied to the MAX31855? Their respective chip selects can not share the same pin.
The Adafruit_MAX31855 bit bangs out an emulated SPI over GPIO. This is not the same as the Wi-Fi's true hard SPI. Once spi.begin(); from SpiUartDevice::begin() then the GPIO pins shared with the hard SPI are no longer available as GPIO. As a result, the Adafruit_MAX31855 bit bangs do nothing. There are several options for the latter problem.
Use a different MAX31855 library that does not bit bang it. But I don't quickly see one.
Fix the Adafruit_MAX31855 to hard SPI.
Use different pins for the MAX31855 other than the Hard SPI pins.
Use the SPI.end() function to shut down the SPI and return GPIO back to normal IO use, and then restart SPI.begin() after bit banging out the Adafruit_MAX31855 function calls.
Such as the following:
SpiSerial.deselect(); //Deselect Wi-Fi
SPI.end(); //Restore GPIO mode of pins
delay(100); //Wait, just for the heck of it
currentTemp = thermocouple.readFarenheit();
SPI.begin(); //Restore SPI mode of pins
SpiSerial.select(); //Reselect Wi-Fi
I want to read the switches next to the LEDS and cycle the LEDS from 0 to whichever switch is pressed
if none are pressed cycle through all of them with the delay.For this i have used timer0. Since I work on
atmega8515. I used INT0.
Here is my implementation:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define BIT(n) (1 << n)
volatile uint8_t led, k, switches, i , j = 1;
/* uint8_t is the same as unsigned char */
int main(void)
{
DDRB = 0xff; /* use all pins on PortB for output */
led = 1; /* init variable representing the LED state */
PORTB = 0XFF;
cli( );
TCCR0|=(1<<CS02) |(1<<CS00);
//Enable Overflow Interrupt Enable
TIMSK|=(1<<TOIE0);
//Initialize Counter
TCNT0=0;
GICR = BIT(INT0);
MCUCR = BIT(ISC01) | BIT(ISC00);
sei( );
for ( ; ;);
}
ISR(TIMER0_OVF_vect)
{
if(switches == 0xff)
{
PORTB = ~led; /* invert the output since a zero means: LED on */
led <<= 1; /* move to next LED */
if (!led) /* overflow: start with Pin B0 again */
{
led = 1;
}
}
else
{
for (k = 0; k< 8;k++)
{
j = switches & (1 << k);
if(j == 0)
{
for(i=1;i<=(k +1);i++)
{
j = 1;
PORTB = ~j;
j = 1 << i;
_delay_ms(100); //without this delay it doesnt cycle the LEDS from to whichever switch is pressed
}
}
}
}
But using delay loops in ISR is a bad programming practice. How to use the same timer instead of the delay?
I think in the ISR, you should just update the LED status and in the main loop you could set the PORTB and read the switches values. In your code, it seems occupy so much time in ISR.