Arduino sensor data - arduino

Hi I am using an Arduino Flex sensor to control a video game character.
The sensor data is being averaged and remapped to a value of between 0-6.
When the player flexes their bicep it reads the max value (this is perfect) however if the player flexes their arm hard and the sensor reads a max value of 6 for some reason as the player relaxes their arm the declining flex values are being passed into the game engine (instead of going from 6 to zero it drops from 6 to 5 to 4 to 3 to 2 to 1 before reaching zero). Can someone please advise how I should alter my code to make the sensor reading return to 0 instead of declining gradually?
#define NUM_LED 6 //sets the maximum numbers of LEDs
#define MAX_Low 75 //for people with low EMG activity
#define MAX_High 150//for people with high EMG activity
#define Threshold 3 // this sets the light to activate TENS
int reading[10];
int finalReading;
int MAX = 0;
int TENS =3;
int ledState = LOW;
byte litLeds = 0;
byte multiplier = 1;
byte leds[] = {8, 9, 10, 11, 12, 13};
char ch;
char contact;
void setup(){
Serial.begin(9600); //begin serial communications
digitalWrite(TENS, LOW);
for(int i = 0; i < NUM_LED; i++){ //initialize LEDs as outputs
pinMode(leds[i], OUTPUT);
pinMode(TENS, OUTPUT); // Set TENS output to StimPin
}
MAX = MAX_High; //This sets the default to people with high EMG activity.
}
void loop(){
for(int i = 0; i < 10; i++){ //take ten readings in ~0.02 seconds
reading[i] = analogRead(A0) * multiplier;
delay(2);
}
for(int i = 0; i < 10; i++){ //average the ten readings
finalReading += reading[i];
}
finalReading /= 10;
for(int j = 0; j < NUM_LED; j++)
{
digitalWrite(leds[j], LOW);//write all LEDs low and stim pin low
}
finalReading = constrain(finalReading, 0, MAX);
litLeds = map(finalReading, 0, MAX, 0, NUM_LED);
Serial.println(litLeds);
for(int k = 0; k < litLeds; k++){
digitalWrite(leds[k], HIGH); // This turns on the LEDS
}
{
// send data only when you receive data:
if (Serial.available() > 0)
{
ch = Serial.read();
contact=digitalRead(TENS);
if (ch == 'A' && contact==LOW)
{
digitalWrite(TENS, HIGH);
}
else if (ch == 'B' && contact==HIGH)
{
digitalWrite(TENS, LOW);
}
}
}
delay(80);
}

Your sensor doesn't read 6 and immediately 0, you are reading it so fast that you can read the intermediate values. For example: if player opens the arm very fast (250-300 ms, it is fast), you can take up to 3 readings then you can read 3 intermediate values.
You can add more time to the last delay() or use only a value that is the same that the 3 last readings to ensure that there isn't a fast change.

Related

Arduino I2C Slave to Master communication problem

I am having a problem with reading random data in my Arduino Mega (Master) from my Arduino Uno (Slave) while using I2C communication.
Some background: I am reading Encoder data from the Uno and sending to the Mega via I2C communication. The encoder data is been used in the MEga to adjust the speed of a motor so that the revolutions per second of the different wheels have the same value.
The issue of reading random data arises when I include an IF condition or function.
Even if the IF condition included is an empty one or a call to function which has an empty body it starts to read random wrong data from the Uno.
If i don't have the adjusting part (IF condition/ function) of the code the reading of the data from the Uno works fine.
If anybody can help, it would be greatly appreciated.
Master Code:
#include <SoftwareSerial.h>
#include <SabertoothSimplified.h>
// Include the required Wire library for I2C<br>#include
#include <Wire.h>
// RX on pin 17 (to S2), TX on pin 16 (to S1).
SoftwareSerial SWSerial(NOT_A_PIN, 16);
// Use SWSerial as the serial port.
SabertoothSimplified ST(SWSerial);
//////////////////ENCODER DATA//////////////////
unsigned int revolutions_L_rpm = 0;
unsigned int revolutions_R_rpm = 0;
int16_t x = 0;
int16_t y = 0;
////////////////////////////////////////////////
//////////////VARIABLES FOR ADJUST//////////////
int error = 0;
int kp = 12;
int adjusted = 0;
////////////////////////////////////////////////
////////////////////MOTORS//////////////////////
//Declare the arduino pins
int LEDg = 7;
int LEDr = 6;
int LEDy = 5;
int speedVar = 0;
int speedOne = 0;
int speedTwo = 0;
int power;
////////////////////END/////////////////////////
void setup() {
//initlize the mode of the pins
pinMode(LEDg,OUTPUT);
pinMode(LEDr,OUTPUT);
pinMode(LEDy,OUTPUT);
//set the serial communication rate
Serial.begin(9600);
SWSerial.begin(9600);
Wire.begin();
}
void loop()
{
//check whether arduino is reciving signal or not
if(Serial.available() > 0){
char val = Serial.read();//reads the signal
Serial.print("Recieved: ");
Serial.println(val);
switch(val){
/*********Increase speed by 1 as long as e(triangle) is held*********/
case 'a':
forward();
break;
/*********Decrease speed by 1 as long as g(x) is held*********/
case 'c':
reverse();
break;
/*********Increase speed by 1 as long as e(triangle) is held*********/
case 'd':
turnLeft();
break;
/*********Decrease speed by 1 as long as g(x) is held*********/
case 'b':
turnRight();
break;
/*********Toggle when Circle is held for 5 seconds*********/
case 'f':
toggleSwitch(LEDy);
break;
/*********Toggle when Square is held for 5 seconds*********/
case 'h':
stopMotors();
break;
}
Serial.print("sppedVar = ");
Serial.print(speedVar);
Serial.print("\tleftSpeed: ");
Serial.print(speedOne);
Serial.print("\trightSpeed: ");
Serial.println(speedTwo);
}
Wire.requestFrom(9,4); // Request 4 bytes from slave arduino (9)
byte a = Wire.read();
Serial.print("a: ");
Serial.print(a);
byte b = Wire.read();
Serial.print(" b: ");
Serial.print(b);
byte e = Wire.read();
Serial.print(" --- e: ");
Serial.print(e);
byte f = Wire.read();
Serial.print(" f: ");
Serial.print(f);
x = a;
x = (x << 8) | b;
Serial.print("\tX: ");
Serial.print(x);
y = e;
y = (y << 8) | f;
Serial.print("\tY: ");
Serial.print(y);
revolutions_L_rpm = x;
revolutions_R_rpm = y;
if ((revolutions_L_rpm != revolutions_R_rpm) && (speedVar != 0)){
error = 0;
error = revolutions_L_rpm - revolutions_R_rpm;
adjusted = error/kp;
Serial.print("Error: ");
Serial.print(error);
Serial.print("Error/kp: ");
Serial.println(adjusted);
if ((speedTwo < 20) && (speedTwo > -20)){
speedTwo -= adjusted;
power = speedTwo;
ST.motor(2, -power);
//delay(20);
}
}
// Print out rpm
Serial.print("Left motor rps*100: ");
Serial.print(revolutions_L_rpm);
Serial.print(" ///// Right motor rps*100: ");
Serial.println(revolutions_R_rpm);
// Print out speed
Serial.print("speedOne: ");
Serial.print(speedOne);
Serial.print("\tspeedTwo: ");
Serial.println(speedTwo);
delay(1000);
}
Slave code:
// Include the required Wire library for I2C<br>#include <Wire.h>
#include <Wire.h>
// Checked for main program
volatile boolean counterReady;
// Internal to counting routine
unsigned int timerPeriod;
unsigned int timerTicks;
unsigned long overflowCount;
// The pin the encoder is connected
int encoder_in_L = 2;
int encoder_in_R = 3;
// The number of pulses per revolution
// depends on your index disc!!
unsigned int pulsesperturn = 16;
// The total number of revolutions
int16_t revolutions_L = 0;
int16_t revolutions_R = 0;
int16_t revolutions_L_rpm = 0;
int16_t revolutions_R_rpm = 0;
// Initialize the counter
int16_t pulses_L = 0;
int16_t pulses_R = 0;
byte myData[4];
// This function is called by the interrupt
void count_L() {
pulses_L++;
}
void count_R() {
pulses_R++;
}
void startCounting(unsigned int ms) {
counterReady = false; // time not up yet
timerPeriod = ms; // how many ms to count to
timerTicks = 0; // reset interrupt counter
overflowCount = 0; // no overflows yet
// Reset timer 2
TCCR2A = 0;
TCCR2B = 0;
// Timer 2 - gives us our 1 ms counting interval
// 16 MHz clock (62.5 ns per tick) - prescaled by 128
// counter increments every 8 µs.
// So we count 125 of them, giving exactly 1000 µs (1 ms)
TCCR2A = bit (WGM21) ; // CTC mode
OCR2A = 124; // count up to 125 (zero relative!!!!)
// Timer 2 - interrupt on match (ie. every 1 ms)
TIMSK2 = bit (OCIE2A); // enable Timer2 Interrupt
TCNT2 = 0; // set counter to zero
// Reset prescalers
GTCCR = bit (PSRASY); // reset prescaler now
// start Timer 2
TCCR2B = bit (CS20) | bit (CS22) ; // prescaler of 128
}
ISR (TIMER2_COMPA_vect){
// see if we have reached timing period
if (++timerTicks < timerPeriod)
return;
TCCR2A = 0; // stop timer 2
TCCR2B = 0;
TIMSK2 = 0; // disable Timer2 Interrupt
counterReady = true;
if(counterReady){
Serial.print("Pulses_L: ");
Serial.print(pulses_L);
Serial.print(" Pulses_R: ");
Serial.println(pulses_R);
// multiplying by 100 to get a greater difference to compare
revolutions_L_rpm = (pulses_L * 100) / pulsesperturn;
revolutions_R_rpm = (pulses_R * 100) / pulsesperturn;
// Total revolutions
// revolutions_L = revolutions_L + (pulses_L / pulsesperturn);
// revolutions_R = revolutions_R + (pulses_R / pulsesperturn);
pulses_L = 0;
pulses_R = 0;
}
}
void requestEvent() {
myData[0] = (revolutions_L_rpm >> 8) & 0xFF;
myData[1] = revolutions_L_rpm & 0xFF;
myData[2] = (revolutions_R_rpm >> 8) & 0xFF;
myData[3] = revolutions_R_rpm & 0xFF;
Wire.write(myData, 4); //Sent 4 bytes to master
}
void setup() {
Serial.begin(9600);
pinMode(encoder_in_L, INPUT);
pinMode(encoder_in_R, INPUT);
attachInterrupt(0, count_L, RISING); //attachInterrupt(digitalPinToInterrupt(encoder_in_L, count_L, RISING);
attachInterrupt(1, count_R, RISING); //attachInterrupt(digitalPinToInterrupt(encoder_in_R, count_R, RISING);
// Start the I2C Bus as Slave on address 9
Wire.begin(9);
// Attach a function to trigger when something is received.
Wire.onRequest(requestEvent);
}
void loop() {
// stop Timer 0 interrupts from throwing the count out
byte oldTCCR0A = TCCR0A;
byte oldTCCR0B = TCCR0B;
TCCR0A = 0; // stop timer 0
TCCR0B = 0;
startCounting (1000); // how many ms to count for
while (!counterReady)
{ } // loop until count over
// Print out rpm
Serial.print("Left motor rps: ");
Serial.println(revolutions_L_rpm);
Serial.print("Right motor rps: ");
Serial.println(revolutions_R_rpm);
// Print out revolutions
// Serial.print("Left motor revolution count: ");
// Serial.println(revolutions_L);
// Serial.print("Right motor revolution count: ");
// Serial.println(revolutions_R);
// restart timer 0
TCCR0A = oldTCCR0A;
TCCR0B = oldTCCR0B;
delay(200);
}

Divided and duplicated frame capture output for ADNS 9800 Arduino

I am trying to interface an ADNS 9800 mouse chip which I took from "Sharkoon SHARK ZONE M50" . The original PCB is still in place.
I am trying to obtain a framecapture, which should be 30 x 30 pixels. I have connected the ADNS 9800 with SPI to an Arduino UNO Rev 3 (i.e. 5V operating voltage). I.e. MISO, MOSI, SCLK, DGND, AGND, NCS. I did not connect any voltage, since I concluded from previous attempts that that did not yield a good frame capture.
The current problem is that I get a frame capture that is divided in 3 parts: square top left (with a good image of the surroundings), square bottom left (which is a duplicate of top left) and a rectangle on the right half of the screen of monotone grey colour (which does change depending on light conditions). See image. I want the full screen to be one image, not the divided mess it is now. Therefore, it may be a question of the resolution that is used, it may be that it is 15x15 instead of 30x30. However I do not know where this is determined/set.
Also, I find it strange that no input voltage seems to be needed to obtain an image from the camera.
See attachments for frame capture and code (arduino + processing).
Frame output
Arduino code
#include
#include
// Registers
#define REG_Product_ID 0x00
#define REG_Revision_ID 0x01
#define REG_Motion 0x02
#define REG_Delta_X_L 0x03
#define REG_Delta_X_H 0x04
#define REG_Delta_Y_L 0x05
#define REG_Delta_Y_H 0x06
#define REG_SQUAL 0x07
#define REG_Pixel_Sum 0x08
#define REG_Maximum_Pixel 0x09
#define REG_Minimum_Pixel 0x0a
#define REG_Shutter_Lower 0x0b
#define REG_Shutter_Upper 0x0c
#define REG_Frame_Period_Lower 0x0d
#define REG_Frame_Period_Upper 0x0e
#define REG_Configuration_I 0x0f
#define REG_Configuration_II 0x10
#define REG_Frame_Capture 0x12
#define REG_SROM_Enable 0x13
#define REG_Run_Downshift 0x14
#define REG_Rest1_Rate 0x15
#define REG_Rest1_Downshift 0x16
#define REG_Rest2_Rate 0x17
#define REG_Rest2_Downshift 0x18
#define REG_Rest3_Rate 0x19
#define REG_Frame_Period_Max_Bound_Lower 0x1a
#define REG_Frame_Period_Max_Bound_Upper 0x1b
#define REG_Frame_Period_Min_Bound_Lower 0x1c
#define REG_Frame_Period_Min_Bound_Upper 0x1d
#define REG_Shutter_Max_Bound_Lower 0x1e
#define REG_Shutter_Max_Bound_Upper 0x1f
#define REG_LASER_CTRL0 0x20
#define REG_Observation 0x24
#define REG_Data_Out_Lower 0x25
#define REG_Data_Out_Upper 0x26
#define REG_SROM_ID 0x2a
#define REG_Lift_Detection_Thr 0x2e
#define REG_Configuration_V 0x2f
#define REG_Configuration_IV 0x39
#define REG_Power_Up_Reset 0x3a
#define REG_Shutdown 0x3b
#define REG_Inverse_Product_ID 0x3f
#define REG_Snap_Angle 0x42
#define REG_Motion_Burst 0x50
#define REG_SROM_Load_Burst 0x62
#define REG_Pixel_Burst 0x64
byte initComplete=0;
byte testctr=0;
unsigned long currTime;
unsigned long timer;
volatile int xdat;
volatile int ydat;
volatile byte movementflag=0;
const int ncs = 10;
const int lsPin = 4;//ANALOG
const int linearActPin = 9;
extern const unsigned short firmware_length;
extern const unsigned char firmware_data[];
String parseChar = ".";
void setup() {
Serial.begin(115200);
//For first parse put LF and CR there
Serial.println("");
//pinMode(ls, INPUT);
//ADNS 9800 setup
pinMode (ncs, OUTPUT);
SPI.begin();
SPI.setDataMode(SPI_MODE3);
SPI.setBitOrder(MSBFIRST);
//Set clock to 2 MHz
SPI.setClockDivider(8);
performStartup();
dispRegisters();
delay(100);
//Pin modes
pinMode(linearActPin, OUTPUT);
Serial.print("Ready");
Serial.println(parseChar);
//Serial.println("Device is ready");
//FrameCapture();
}
/* DO NOT EDIT BELOW; NECESSARY FOR ADNS9800 */
void performStartup(void){
// reset the chip
adns_com_end(); // ensure that the serial port is reset
adns_com_begin(); // ensure that the serial port is reset
adns_com_end(); // ensure that the serial port is reset
adns_write_reg(REG_Power_Up_Reset, 0x5a); // force reset
delay(50); // wait for it to reboot
// read registers 0x02 to 0x06 (and discard the data)
adns_read_reg(REG_Delta_X_L);
adns_read_reg(REG_Delta_X_H);
adns_read_reg(REG_Delta_Y_L);
adns_read_reg(REG_Delta_Y_H);
// upload the firmware
adns_upload_firmware();
delay(10);
//enable laser(bit 0 = 0b), in normal mode (bits 3,2,1 = 000b)
// reading the actual value of the register is important because the real
// default value is different from what is said in the datasheet, and if you
// change the reserved bytes (like by writing 0x00...) it would not work.
byte laser_ctrl0 = adns_read_reg(REG_LASER_CTRL0);
adns_write_reg(REG_LASER_CTRL0, laser_ctrl0 & 0xf1 );
//0x08 = enable fixed framerate, leave rest standard
//0x10 = disable AGC, leave rest standard
adns_write_reg(REG_Configuration_II, 0x08);
//Set resolution; cpi = REG_value x50
//Min: 0x01 50 cpi
//Max: 0xA4 8200 cpi
adns_write_reg(REG_Configuration_I, 0xA4);
//Set fixed framerate: FR = clk_freq/REG_value = 2000 fps
adns_write_reg(REG_Frame_Period_Max_Bound_Lower, 0xa8);
adns_write_reg(REG_Frame_Period_Max_Bound_Upper, 0x61);
//Set shutter time
adns_write_reg(REG_Shutter_Max_Bound_Lower,0x00);
adns_write_reg(REG_Shutter_Max_Bound_Upper,0x08);
//adns_write_reg(REG_Snap_Angle, 0x80);
delay(1);
Serial.print("Initialized");
Serial.println(parseChar);
}
void adns_com_begin(){
digitalWrite(ncs, LOW);
}
void adns_com_end(){
digitalWrite(ncs, HIGH);
}
byte adns_read_reg(byte reg_addr){
adns_com_begin();
// send adress of the register, with MSBit = 0 to indicate it's a read
SPI.transfer(reg_addr & 0x7f );
delayMicroseconds(100); // tSRAD
// read data
byte data = SPI.transfer(0);
delayMicroseconds(1); // tSCLK-NCS for read operation is 120ns
adns_com_end();
delayMicroseconds(19); // tSRW/tSRR (=20us) minus tSCLK-NCS
return data;
}
void adns_write_reg(byte reg_addr, byte data){
adns_com_begin();
//send adress of the register, with MSBit = 1 to indicate it's a write
SPI.transfer(reg_addr | 0x80 );
//sent data
SPI.transfer(data);
delayMicroseconds(20); // tSCLK-NCS for write operation
adns_com_end();
delayMicroseconds(100); // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
}
void adns_upload_firmware(){
// send the firmware to the chip, cf p.18 of the datasheet
//Serial.println("Uploading firmware...");
// set the configuration_IV register in 3k firmware mode
adns_write_reg(REG_Configuration_IV, 0x02); // bit 1 = 1 for 3k mode, other bits are reserved
// write 0x1d in SROM_enable reg for initializing
delay(10);
adns_write_reg(REG_SROM_Enable, 0x1d);
// wait for more than one frame period
delay(10); // assume that the frame rate is as low as 100fps... even if it should never be that low
// write 0x18 to SROM_enable to start SROM download
adns_write_reg(REG_SROM_Enable, 0x18);
// write the SROM file (=firmware data)
adns_com_begin();
//write burst destination adress
//bitwise OR to ensure MSB is 1
SPI.transfer(REG_SROM_Load_Burst | 0x80);
delayMicroseconds(50);
// send all bytes of the firmware
unsigned char c;
for(int i = 0; i < firmware_length; i++){
c = (unsigned char)pgm_read_byte(firmware_data + i);
SPI.transfer(c);
delayMicroseconds(15);
}
adns_com_end();
}
void adns_frame_capture(){
//Send signal to start datacollection frame capture
Serial.print("Frame capture");
Serial.println(parseChar);
// reset the chip
adns_write_reg(REG_Power_Up_Reset, 0x5a); // force reset
delay(50); // wait for it to reboot
delay(10);
//Write bytes to Frame_Capture
adns_write_reg(REG_Frame_Capture, 0x93);
adns_write_reg(REG_Frame_Capture, 0xc5);
// wait for more than two frame periods
delay(25); // assume that the frame rate is as low as 100fps... even if it should never be that low
//Check for the first pixel bij reading bit zero of Motion register
//If it is 1, first pixel available
byte motion = adns_read_reg(REG_Motion);
adns_com_begin();
delayMicroseconds(120);//delay t-SRAD = 100 us
byte pixel_burst;
if (motion == 0x21){
//Reading pixel values from ADNS and storing them in Array
for(int i = 0; i < 900; i++){
pixel_burst = adns_read_reg(REG_Pixel_Burst);
//Serial.print(i);
//Serial.print(":");
Serial.print(String(pixel_burst));
Serial.println(parseChar);
delayMicroseconds(15);
}
//Finished transmitting data
Serial.print("Data transfer finished");
Serial.println(parseChar);
//Transfer surface quality value
Serial.print("SQUAL");
Serial.print(String(adns_read_reg(REG_SQUAL)));
Serial.println(parseChar);
}else {
Serial.print("Frame capture failed");
Serial.println(parseChar);
}
adns_com_end();
//Hardware reset and firmware restore required to return navigation
performStartup();
}
void dispRegisters(void){
int oreg[7] = {
0x00,0x3F,0x2A,0x02 };
char* oregname[] = {
"Product_ID","Inverse_Product_ID","SROM_Version","Motion" };
byte regres;
digitalWrite(ncs,LOW);
int rctr=0;
for(rctr=0; rctr<4; rctr++){
SPI.transfer(oreg[rctr]);
delay(1);
//Serial.println("---");
//Serial.println(oregname[rctr]);
//Serial.println(oreg[rctr],HEX);
regres = SPI.transfer(0);
//Serial.println(regres,BIN);
//Serial.println(regres,HEX);
delay(1);
}
digitalWrite(ncs,HIGH);
}
/*********************************************************
DO NOT EDIT ABOVE; NECESSARY FOR RUNNING ADNS9800
*********************************************************/
String data = String();
//Process variables
int run = 0;
int t = 0;
unsigned long t_ms, t_us;
int dt = 0;//1/f = [ms]
long int t_run = 0;//[ms]
unsigned long ms_start, us_start;
void loop() {
if (dt == -1 || t_run == -1){
Serial.print("Time constant error");
Serial.println(parseChar);
}else if (run == 1 && t<t_run){
measure();
Serial.print(data);
Serial.println("");
Serial.println(parseChar);
}else if(run == 1 && t>=t_run){
//Measurement finished
Serial.print("Measurement finished");
Serial.println(parseChar);
digitalWrite(linearActPin, LOW);
run = 0;
t = 0;
}
}
void serialEvent(){
String data_rx;
if (Serial.available() > 0){
//Parse serial data until '.'
data_rx = Serial.readStringUntil('.');
//Remove '.' from buffer
data_rx = data_rx.substring(0, data_rx.length());
//Serial.print(data_rx);
if (data_rx.equals("Run")){
run = 1;
ms_start = millis();
us_start = micros();
digitalWrite(linearActPin, HIGH);
//Read registers and discard data
byte XDataL = adns_read_reg(REG_Delta_X_L);
byte XDataH = adns_read_reg(REG_Delta_X_H);
byte YDataL = adns_read_reg(REG_Delta_Y_L);
byte YDataH = adns_read_reg(REG_Delta_Y_H);
}else if(data_rx.equals("Frame capture run")){
adns_frame_capture();
}else if(data_rx.equals("SQUAL")){
Serial.println(String(adns_read_reg(REG_SQUAL)));
}else if(data_rx.startsWith("dt")){
dt = data_rx.substring(2,data_rx.length()).toInt();
}else if(data_rx.startsWith("trun")){
t_run = data_rx.substring(4,data_rx.length()).toInt();
}
}
}
void measure(void){
/*READ dx, dy, ls
increment t with dt
return String "t,dx,dy,ls"*/
//Read optic flow from ADNS
byte XDataL = adns_read_reg(REG_Delta_X_L);
byte XDataH = adns_read_reg(REG_Delta_X_H);
byte YDataL = adns_read_reg(REG_Delta_Y_L);
byte YDataH = adns_read_reg(REG_Delta_Y_H);
int ls;
unsigned long us, ms;
xdat = int(XDataH<<8);
ydat = int(YDataH<<8);
xdat |=int(XDataL);
ydat |=int(YDataL);
//int between 0-1023, with 5V/1024 = 0.0049 V/unit
ls = analogRead(lsPin);
//Calculate time elapsed between measurements
ms = millis();
us = micros();
t_ms = ms-ms_start;
t_us = us-us_start;
t = t_ms;
//Convert datatypes to string objects and combine
//us can always be divided by 4, so accurate to a resolution of 4 us
String d1 = String(t_ms);
String d2 = String(t_us);
String d3 = String(xdat);
String d4 = String(ydat);
String d5 = String(ls);
data = d2+","+d3+","+d4+","+d5;
//Increment time
delay(dt);
}
Processing code
/* BEP experiment
Communicates with arduino to conduct experiment
Receives and stores data
/
/ DATA PROTOCOL
data_rx
R start measuring
S do screendump
D device is ready
F measurement finished
/
import processing.serial.;
import controlP5.*;
//Serial COMM
Serial arduino;
String data_rx, data_tx;
String parseChar = ".";
//GUI
ControlP5 cp5;
Textfield txtfldDistance, txtfldSpeed, txtfldTs, txtfldN,
txtfldFl, txtfldBron, txtfldPattern, txtfldTrun;
Button btnRun, btnStop, btnFrame;
//File I/O
PrintWriter writer;
String path;
//Runtime variables
int run = 0;
int createWriter = 0;
int frameCapture = 0;
int frameDisplay = 0;
//Time management
String timestamp;
int ms, ms_start;
final int frameX = 30;
final int frameY = 30;
void setup() {
frameRate(60);
time();
//Create GUI
textSize(20);
size(360,660);
//Create textboxes
cp5 = new ControlP5(this);
txtfldDistance = cp5.addTextfield("Distance[m]:")
.setPosition(30, 30)
.setSize(70, 30)
.setAutoClear(false)
.setText("0.5");
txtfldSpeed = cp5.addTextfield("Speed[rev/s]:")
.setPosition(30, 90)
.setSize(70, 30)
.setAutoClear(false);
txtfldTs = cp5.addTextfield("t_s[ms]")
.setPosition(30, 150)
.setSize(70, 30)
.setAutoClear(false)
.setText("10");
txtfldTrun = cp5.addTextfield("t_run[s]")
.setPosition(30, 210)
.setSize(70, 30)
.setAutoClear(false);
txtfldFl = cp5.addTextfield("f[mm]")
.setPosition(130, 30)
.setSize(70, 30)
.setAutoClear(false)
.setText("14");
txtfldBron = cp5.addTextfield("Bron[Watt]")
.setPosition(130, 90)
.setSize(70, 30)
.setAutoClear(false)
.setText("40");
txtfldPattern = cp5.addTextfield("Pattern[mm]")
.setPosition(130, 150)
.setSize(70, 30)
.setAutoClear(false)
.setText("random");
txtfldN = cp5.addTextfield("n")
.setPosition(130, 210)
.setSize(70, 30)
.setAutoClear(false)
.setText("1");
btnRun = cp5.addButton("Run")
.setPosition(230, 270)
.setSize(50,30)
.lock();
btnStop = cp5.addButton("Stop")
.setPosition(150, 270)
.setSize(50,30)
.lock();
btnFrame = cp5.addButton("Frame_Capture")
.setPosition(30, 270)
.setSize(90,30)
.lock();
//Create Serial COMM object
print(timestamp+"SERIAL PORT: ");
println(Serial.list());
// List all the available serial ports:
//arduino = new Serial(this, Serial.list()[2], 115200);
arduino = new Serial(this, Serial.list()[0], 115200);
arduino.clear();
arduino.bufferUntil('.');
}
void draw() {
time();
Frame_Capture();
display_frame();
if (frameDisplay == 1){
display_frame();
frameDisplay = 0;
println(timestamp+"---------------------");
}
}
int n = 0;
int[] frame_capture_data = new int[900];
void serialEvent(Serial arduino){
if (arduino.available() > 0){
//Parse serial data until '.'
data_rx = arduino.readStringUntil('.');
//Remove CR, LF and '.' from buffer
data_rx = data_rx.substring(2, data_rx.length()-1);
//print(n+":");
//println(data_rx);
if(data_rx.equals("Data transfer finished")){
println(timestamp+"Data transfer finished.");
println(timestamp+"Generating visual.");
frameCapture = 0;
frameDisplay = 1;
n = 0;
//unlock textfields
txtfldSpeed.unlock();
txtfldDistance.unlock();
txtfldTs.unlock();
txtfldBron.unlock();
txtfldPattern.unlock();
txtfldFl.unlock();
txtfldN.unlock();
btnRun.unlock();
btnStop.unlock();
btnFrame.unlock();
}else if(data_rx.equals("Ready")){
println(timestamp+"Device is ready.");
println(timestamp+"---------------------");
//unlock textfields
btnRun.unlock();
btnStop.unlock();
btnFrame.unlock();
}else if(data_rx.equals("Initialized")){
println(timestamp+"Device is initialized.");
}else if(data_rx.equals("Measurement finished")){
println(timestamp+"Measurement completed.");
Stop();
}else if(data_rx.equals("Frame capture")){
println(timestamp+"Frame capture transfer started.");
frameCapture = 1;
}else if(data_rx.equals("Frame capture failed")){
println(timestamp+"Frame capture failed. Try again.");
println(timestamp+"---------------------");
//unlock textfields
txtfldSpeed.unlock();
txtfldDistance.unlock();
txtfldTs.unlock();
txtfldBron.unlock();
txtfldPattern.unlock();
txtfldFl.unlock();
txtfldN.unlock();
btnRun.unlock();
btnStop.unlock();
btnFrame.unlock();
}else if(data_rx.contains("SQUAL")){
print(timestamp+"SQUAL: ");
println(data_rx.substring(5,data_rx.length()));
}else if(data_rx.equals("Time constant error")){
print(timestamp+"TIME CONSTANT ERROR");
}else if(frameCapture == 1 && n < 900){
frame_capture_data[n] = int(data_rx);
n++;
}else if(run == 1){
//print(data_rx);
writer.print(data_rx);
}
}
}
public void Run() {
/* When RUN is pressed program starts to run */
//Read value to determine path
float speed = float(txtfldSpeed.getText());
float distance = float(txtfldDistance.getText());
int t_s = int(txtfldTs.getText());
int bron = int(txtfldBron.getText());
int fl = int(txtfldFl.getText());
String pattern = txtfldPattern.getText();
String date = day()+"-"+month();
int n = int(txtfldN.getText());
// Create CSV data file, showing the results from experiment
if (speed > 0 && distance > 0){
if (createWriter == 0){
//Creating objects for writing to file
path = "data/"+date+"/x="+distance+"/"+"x="+distance+"_v="+speed+
"_ts="+t_s+"_f="+fl+"_bron="+bron+"_pat="+pattern+"_n="+n+".csv";
writer = createWriter(path);
//Runtime variables
createWriter = 1;
run = 1;
ms_start = millis();
//Transmit t_s en t_run
arduino.write("dt"+txtfldTs.getText());
arduino.write(parseChar);
arduino.write("trun"+int(txtfldTrun.getText())*1000);
arduino.write(parseChar);
//Transmit starting char to arduino
arduino.write("Run");
arduino.write(parseChar);
//Header
//writer.println("t_ard_ms,t_ard_us,dx,dy,ls");
//lock textfields
txtfldSpeed.lock();
txtfldDistance.lock();
txtfldTs.lock();
txtfldBron.lock();
txtfldPattern.lock();
txtfldFl.lock();
txtfldN.lock();
btnRun.lock();
btnStop.lock();
btnFrame.lock();
println(timestamp+"PROGRAM INITIATED");
println(timestamp+"File stored at: "+path);
}
//ERROR messages
} else if (speed <= 0 && distance <= 0){
println(timestamp+"ERROR: INVALID SPEED AND DISTANCE");
} else if (speed <= 0){
println(timestamp+"ERROR: INVALID SPEED");
} else if (distance <= 0){
println(timestamp+"ERROR: INVALID DISTANCE ");
} else if(txtfldSpeed.getText().equals("")){
println(timestamp+"ERROR: Enter paramaters.");
}
}
public void Stop() {
/* When STOP is pressed program terminates and writes to file */
if (createWriter == 1){
//Write to file and close stream
writer.flush();
writer.close();
//Runtime variables
run = 0;
createWriter = 0;
//unlock textfields
txtfldSpeed.unlock();
txtfldDistance.unlock();
txtfldTs.unlock();
txtfldBron.unlock();
txtfldPattern.unlock();
txtfldFl.unlock();
txtfldN.unlock();
btnRun.unlock();
btnStop.unlock();
btnFrame.unlock();
txtfldN.setText(str(int(txtfldN.getText())+1));
if (int(txtfldN.getText()) > 5){
txtfldN.setText("1");
txtfldSpeed.clear();
}
println(timestamp+"Data written to file.");
println(timestamp+"---------------------");
}
}
public void Frame_Capture() {
arduino.write("Frame capture run");
arduino.write(parseChar);
//lock textfields
txtfldSpeed.lock();
txtfldDistance.lock();
txtfldTs.lock();
txtfldBron.lock();
txtfldPattern.lock();
txtfldFl.lock();
txtfldN.lock();
btnRun.lock();
btnStop.lock();
btnFrame.lock();
}
void display_frame(){
int[] frame1 = new int[225];
int[] frame2 = new int[255];
int x = 30;
int y = 320;
//resolutie 10x10
int s = 10; // size of pixel, i.e. side lengths
//Max res is 30x30
int sz = 10;
int res = 30;
for (int i = 0; i < 15; i++){
for (int m = 0; m < 15; m++){
frame1[15*i+m] = frame_capture_data[30*i+m];
frame2[15*i+m] = frame_capture_data[30*i+m+15];
}
}
//for (int i = 0; i < res*res; i++){
//Commented by Daan:
//for (int j = 0; j < res; j++){ // j resembles the column index.
// for (int k = 0; k < res; k++){ // k resembles the row index
// //fill(map(frame_capture_data[30*j+k],0,63,0,255));
// //frame_capture_data[30*j+k] = 300; // test to see how the pixel values can be manipulated
// fill(float(frame_capture_data[30*j+k]));
// rect(x+j*10, y+300-k*10, s, s);
// //println(frame_capture_data[30*j+k]);
// }
//}
for( int i = 0; i < 900; i++ )
{
fill( map(frame_capture_data[i], 0, 63, 0, 255) ); // Convert from ADNS greyscale to 0 - 255 grey scale format.
rect(x + (i / frameX * sz), // Each rect() is a rectangle that represents a pixel. I.e. width and height of each pixel is "sz".
y +300 - (i % frameY * sz),
sz, sz);
// //rect(off_x + (i % frameX * sz), // Each rect() is a rectangle that represents a pixel. I.e. width and height of each pixel is "sz".
// //off_y + (i / frameY * sz),
// //sz, sz);
}
fill(255,0,0);
rect(x+3*10, y+300-8*10, s, s); // this is red test dot, j = 3 (column), k = 8 (row).
// I.e. this is the 30*3 + 8 = 98 th pixel in frame stream from sensor.
}
public void time(){
/* Keeps track of time
Creates timestamp for messages*/
String h = str(hour());
String m = str(minute());
String s = str(second());
if (int(h) < 10){
h = "0"+h;
} else if(int(m) < 10){
m = "0"+m;
} else if(int(s) < 10){
s = "0"+s;
}
timestamp = "["+h+":"+m+":"+s+"] ";
}

Arduino pulse train

I will give you a little introduction:
I am working on a water fuel cell of Stanley Meyer. For those who don't know the water fuel cell you can see it here.
For the water fuel cell one has to build a circuit. Here is the diagram:
Right now I am working on the pulse generator (variable) and the pulse gate (variable) to generate this waveform.
So, I want to do this with Arduino timers. I already can generate a "high frequency" pulse generator (1 kHz - 10 kHz, depending on the prescaling at the TCCR2B register) PWM at pin 3 with this code:
pinMode(3, OUTPUT);
pinMode(11, OUTPUT);
TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS21) | _BV(CS20);
OCR2A = 180;
OCR2B = 50;
I can modify the frequency and pulse with:
sensorValue = analogRead(analogInPin);
sensorValue2 = analogRead(analogInPin2);
// Map it to the range of the analog out:
outputValue = map(sensorValue, 0, 1023, 30, 220);
outputValue2 = map(sensorValue2, 0, 1023, 10, 90);
OCR2A = outputValue;
This is working fine.
Now I want to modulate this pulse with another pulse train with "low frequency" (20 Hz to 100 Hz approximately) to act as a pulse gate. I was thinking to use Timer 0 to count and shutdown the signal when it counts some value and activate when arrives at the same value again, like this
TCCR0A = _BV(COM0A0) | _BV(COM0B0) | _BV(WGM01);
TCCR0B = _BV(CS02);
OCR0A = 90;
OCR0B = OCR0A * 0.8;
And compare with the counter
if (TCNT0 <= OCR0A)
TCCR2A ^= (1 << COM2A0);
But it does not work well. Any ideas for this?
These days I have tried to create a wave generator like the one that comes in your question. I can not eliminate the jitter or mismatch that appears, but I can create a wave like that. Try this example and modify it:
#include <TimerOne.h>
const byte CLOCKOUT = 11;
volatile byte counter=0;
void setup() {
Timer1.initialize(15); // Every 15 microseconds change the state
// of the pin in the wave function giving
// a period of 30 microseconds
Timer1.attachInterrupt(Onda);
pinMode(CLOCKOUT, OUTPUT);
digitalWrite(CLOCKOUT, HIGH);
}
void loop() {
if (counter>=29) { // With 29 changes I achieve the amount of pulses I need.
Timer1.stop(); // Here I create the dead time, which must be in HIGH.
PORTB = B00001000;
counter = 0;
delayMicroseconds(50);
Timer1.resume();
}
}
void Onda(){
PORTB ^= B00001000; // Change pin status
counter += 1;
}

Arduino shield, SD card Data logge, why are my SD cards dying?

I'm having a real anoying problem that I carnt seem to find a solution on.
I have created a simple arduino code for sweeping a curve on 2 analog pin, controlled by a DAC unit. The sweeps are being done in real time, ones a second, and is stored on a SD card in files split into hours.
My problem is that my SPI interface on the SD cards stop responding during continues used.
I use the following arduino mega shield
http://pcb.daince.net/doku.php?id=data_logger
and a "Kingston MicroSDHC 4GB Secure Digital Card, 66X" for storage
I ran the the following code for 3 days and when I came back the SPI was none responding (I have done 1 hours tests before with no problem, and I have checked that the system changes files correctly)
#include "SPI.h"
#include <SD.h>
#include "Wire.h"
//Static definitions
#define ADG509_A0_pin 39
#define ADG509_A1_pin 38
#define SS_DAC_pin 53
#define voltage_analog_pin 11
#define current_analog_pin 12
#define led 13
#define DS1307_ADDRESS 0x68
#define chip_select 53
//Adjustable definitions
#define ADC_to_voltage 1/213 // the value for converting the arduino ADC to voltage
#define number_of_samples 100 //number of measurements, should be able to be divided by 4 without giving decimals
#define time_per_data_set 500 //the delay between datasets in milisecondss, note the the "delay = system_computation_time + time_per_data_set"
#define current_gain_ratio 2 //the realtion between the voltage level on the pin and current on from the solar pannel
#define voltage_gain_ratio 10 //the realtion between the voltage level on the pin and the voltage level from the solar panel
#define number_samples_per_measurement 5 //the number of ADC readings used to make an average of each measuring point, note this number greatly effects sweeping time
#define delay_per_measurement 1
void set_DAC(float value); // gets an input between 0.0 and 5.0 and sets the voltage to the value
void write_measurement_to_SD(float current, float voltage, int number); //writes the numbers to the SD card if initialized
void write_to_file(); //check is a new SD card file should be created and makes it ef nessesary. Also handles the data writing to the file
void get_time(); //Get the current time of the system, and store them in global variables
int bcdToDec(byte val); //Converts bytes to decimals numbers
char intToChar(int val, int number); //Converts integers to chars, only exept up to 2 dicimals
word output_word_for_DAC = 0; //used to type cast input of set_DAC to word before usage
byte data = 0; //temp variable need for DAC, it is the byte send over the communication
float volt; //stores a temporary voltage measurement
float current; //stores a temporary current measurement
float current_level; //stores the short curciut current level, it is used to find the optimal placement for measuring points
char filename[13] = "F0000000.txt"; //stores the current active filename for writing on the SD card
File dataFile; //the current version of the datafile on the SD card
int years, months, monthsDay, weekDay, hours, minute, seconds; //global varibles used to store the last time reading
float current_array[number_of_samples]; //used to store all current measurements points during sweep
float voltage_array[number_of_samples]; //used to store all voltage measurements points during sweep
int typecast_int; // used for typecasting float to int
int last_measurement_time;
int is_SDcard_there;
void setup() {
pinMode(ADG509_A0_pin, OUTPUT);
pinMode(ADG509_A1_pin, OUTPUT);
pinMode(SS_DAC_pin, OUTPUT);
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
digitalWrite(ADG509_A1_pin, LOW);
digitalWrite(ADG509_A0_pin, LOW);
SPI.begin(); // start up the SPI bus
SPI.setBitOrder(MSBFIRST);
Wire.begin();
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {;}
Serial.print("Initializing SD card...");
if (!SD.begin(chip_select)) {
Serial.println("Card failed, or not present");
is_SDcard_there = 0;
return;+
}
Serial.println("card initialized.");
is_SDcard_there = 1;
}
void loop() {
//finding the shortcurcuit current of the solar panel
get_time();
last_measurement_time = seconds;
set_DAC(5); //open fet
delayMicroseconds(1000);
current_level = analogRead(current_analog_pin);
for(float counter2 = 0; counter2 < 10; counter2++){
current_level += analogRead(current_analog_pin);
}
current_level = (current_level/10)* 1.1 * ADC_to_voltage;
//fully opening the fet to insure that the solar pannel is stable at max voltage before beginning the sweep
set_DAC(0); //ground fet
delayMicroseconds(10000);
if(is_SDcard_there == 1){
digitalWrite(led, HIGH);
}
//sweeping the first 80% current on the curve with 25% of the measuring points
//note no calculations should be put in here, since it slow the sweep down
for(float counter = 0; counter < number_of_samples * 0.25; counter++){
set_DAC((counter*current_level * 0.80) / (number_of_samples * 0.25));
delayMicroseconds(200);
current = analogRead(current_analog_pin);
volt = analogRead(voltage_analog_pin);
for(float counter2 = 0; counter2 < number_samples_per_measurement - 1; counter2++){
current += analogRead(current_analog_pin);
volt += analogRead(voltage_analog_pin);
}
current = current / number_samples_per_measurement;
volt = volt / number_samples_per_measurement;
typecast_int = counter;
current_array[typecast_int] = current;
voltage_array[typecast_int] = volt;
}
//sweeping the last 20% current on the curve with 75% of the measuring points
//note no calculations should be put in here, since it slow the sweep down
for(float counter = 0; counter < number_of_samples * 0.75; counter++){
set_DAC(current_level * 0.80 + (counter*current_level * 0.20) / (number_of_samples * 0.75));
delayMicroseconds(200);
current = analogRead(current_analog_pin);
volt = analogRead(voltage_analog_pin);
for(float counter2 = 0; counter2 < number_samples_per_measurement - 1; counter2++){
current += analogRead(current_analog_pin);
volt += analogRead(voltage_analog_pin);
}
current = current / number_samples_per_measurement;
volt = volt / number_samples_per_measurement;
typecast_int = counter + number_of_samples * 0.25;
current_array[typecast_int] = current;
voltage_array[typecast_int] = volt;
}
set_DAC(5); //sets DAC high to prepare for next short curcuit measurement
digitalWrite(led, LOW);
//converting data to desired values and writing them to the file
String to_write = "";
int check;
char buffer[20];
to_write = "0,0,-2";
to_write += '\r';
to_write += '\n';
to_write += "0,";
to_write += intToChar(minute,0);
to_write += intToChar(minute,1);
to_write += intToChar(seconds,0);
to_write += intToChar(seconds,1);
to_write += ",-1";
to_write += '\r';
to_write += '\n';
for(int counter = 0; counter < number_of_samples-1; counter++){
to_write += dtostrf(current_array[counter] = current_array[counter] * ADC_to_voltage * current_gain_ratio, 0, 2, buffer);
to_write += ",";
to_write += dtostrf(voltage_array[counter] = voltage_array[counter] * ADC_to_voltage * voltage_gain_ratio, 0, 2, buffer);
to_write += ",";
to_write += counter;
to_write += '\r';
to_write += '\n';
}
to_write += dtostrf(current_array[99] = current_array[99] * ADC_to_voltage * current_gain_ratio, 0, 2, buffer);
to_write += ",";
to_write += dtostrf(voltage_array[99] = voltage_array[99] * ADC_to_voltage * voltage_gain_ratio, 0, 2, buffer);
to_write += ",99";
Serial.println(to_write); //should only be used for debugging since it slow down the system to much
compute_filename(); //initialize a new filename if needed
check = 0;
while(check == 0 && is_SDcard_there == 1){
dataFile = SD.open(filename,FILE_WRITE);
check = dataFile.println(to_write);
if (dataFile){
dataFile.close();
}
}
//wait for next seconds
while(last_measurement_time + delay_per_measurement > seconds){
get_time();
if(seconds < last_measurement_time){seconds = seconds + 60;}
}
}
// gets an input between 0.0 and 5.0 and sets the voltage to the value
void set_DAC(float value){
if(value <= 5){
value = value*819;
int conveter = value;
output_word_for_DAC = conveter;
digitalWrite(SS_DAC_pin, LOW);
data = highByte(output_word_for_DAC);
data = 0b00001111 & data;
data = 0b00110000 | data;
SPI.transfer(data);
data = lowByte(output_word_for_DAC);
SPI.transfer(data);
digitalWrite(SS_DAC_pin, HIGH);
}
}
//writes the numbers to the SD card if initialized
void write_measurement_to_SD(float current, float voltage, int number){
dataFile = SD.open(filename,FILE_WRITE);
dataFile.print(current);
dataFile.print(',');
dataFile.print(voltage);
dataFile.print(',');
dataFile.print(number);
dataFile.println(';');
if (dataFile){
dataFile.close();
}
}
//Converts bytes to decimals numbers
int bcdToDec(byte val){
return ( (val/16*10) + (val%16) );
}
//Converts integers to chars, only exept up to 2 dicimals
char intToChar(int val, int number){ // note it only take ints with 2 digits
String tempString = "";
char returnValue[3];
if(val < 10){
tempString += 0;
}
tempString += val;
tempString.toCharArray(returnValue,3);
return returnValue[number];
}
//Get the current time of the system, and store them in global variables
void get_time(){
Wire.beginTransmission(DS1307_ADDRESS);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
seconds = bcdToDec(Wire.read());
minute = bcdToDec(Wire.read());
hours = bcdToDec(Wire.read() & 0b111111); //24 hours time
weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
monthsDay = bcdToDec(Wire.read());
months = bcdToDec(Wire.read());
years = bcdToDec(Wire.read());
}
//check if the system need a new filename
void compute_filename(){
get_time();
filename[1] = intToChar(years,1);
filename[2] = intToChar(months,0);
filename[3] = intToChar(months,1);
filename[4] = intToChar(monthsDay,0);
filename[5] = intToChar(monthsDay,1);
filename[6] = intToChar(hours,0);
filename[7] = intToChar(hours,1);
if (dataFile){
dataFile.close();
}
}
I know that this is a big code dump and I'm sorry for that, but I carnt realy cut it down when I have no idea what is killing my SD cards.
Any help on the matter is appreciated
and any ideas on what I can test to isolate or locate the error is also welcome
there can be 2 possible errors:
1 resource leak
2 RAM overflow
for 1 you can put some code that write on serial RAM usage evry loop(), if that number grow, some library (as you aren't allocating memory with alloc() )is broken. For 2, don't build up to_write, but use directly Serial.println(), alyas try to use array/string wicth use LESS than 100 byte or you might have problem (String dinamically allocate space, and that allocation can fail.. silently. then bad things appen)
I've done a lot of work with SD cards during the past 10 years and I've noticed that the SD card is very easily bricked into a non-responsive mode if it receives garbage in the CMD line. It seems that at least some kind of garbage is interpreted as a command to set the card password, thus locking the card. It has happened to me at least 10 times in as many years when I've been working with SD library code or new hardware designs, so it looks to me that it must be some bit patterns which is easily generated somehow.
I've been able to rescue the (micro)SD cards by putting them into my old Symbian phone which immediately recognizes that the card is locked and offers to reformat the card and reset the password. You might try the same with your SD card, to see if your problem is the same I've experienced. I remember vaguely that some cheap Canon camera was also able to rescue some card in a similar way.

Arduino issues with fsr and LCD

I am doing a project which requires the use of arduino uno, 4 force sensors and a 16x2 LCD. I'm trying to display the readings of the force sensors onto the LCD with the implementation of the buttons. For eg. if I press the up button it should display the first force sensor reading. The problem is it just displays a huge number of 143164976.0000 even when no force is applied on it. Please advice on whether there is a problem to my coding.
int iForceSensorReading; // the analog reading from the FSR resistor divider
int iForceSensorReading1;
int iForceSensorReading2;
int iForceSensorReading3;
int iForceSensorVoltage; // the analog reading converted to voltage
int iForceSensorVoltage1;
int iForceSensorVoltage2;
int iForceSensorVoltage3;
unsigned long ulForceSensorResistance;// The voltage converted to resistance, can be very big so make "long"
unsigned long ulForceSensorResistance1;
unsigned long ulForceSensorResistance2;
unsigned long ulForceSensorResistance3;
unsigned long ulForceSensorConductance;
unsigned long ulForceSensorConductance1;
unsigned long ulForceSensorConductance2;
unsigned long ulForceSensorConductance3;
float FsrForce = 0; // Finally, the resistance converted to force
float FsrForce1 = 0;
float FsrForce2 = 0;
float FsrForce3 = 0;
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7
void setup(void){
Serial.begin(9600); // send debugging information via the Serial monitor
lcd.begin(16, 2);
lcd.print("Hand Muscle");
lcd.setCursor(0,1);
lcd.print("Meter");
lcd.setBacklight(WHITE);
}
uint8_t i=0;
void loop(void){
uint8_t buttons = lcd.readButtons();
iForceSensorReading = analogRead(A0);//read index finger pressure
delay(30);
// analog voltage reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
iForceSensorVoltage = map(iForceSensorReading, 0, 1023, 0, 5000);
ulForceSensorConductance = conductanceFunction(ulForceSensorResistance, iForceSensorVoltage);
if (ulForceSensorConductance <= 1000){
FsrForce = ulForceSensorConductance / 80;
}
else{
FsrForce = ulForceSensorConductance - 1000;
FsrForce /= 30;
}
iForceSensorReading1 = analogRead(A1);//read middle finger pressure
delay(30);
iForceSensorVoltage1 = map(iForceSensorReading1, 0, 1023, 0, 5000);
if (iForceSensorVoltage1 == 0){
}
else{
ulForceSensorConductance1 = conductanceFunction(ulForceSensorResistance1, iForceSensorVoltage1);
delay(30);
}
if (ulForceSensorConductance1 <= 1000){
FsrForce1 = ulForceSensorConductance1 / 80;
}
else{
FsrForce1 = ulForceSensorConductance1 - 1000;
FsrForce1 /= 30;
}
iForceSensorReading2 = analogRead(A2);// read ring finger pressure
delay(30);
iForceSensorVoltage2 = map(iForceSensorReading2, 0, 1023, 0, 5000);
ulForceSensorConductance2 = conductanceFunction(ulForceSensorResistance2, iForceSensorVoltage2);
if (ulForceSensorConductance2 <= 1000){
FsrForce2 = ulForceSensorConductance2 / 80;
}
else{
FsrForce2 = ulForceSensorConductance2 - 1000;
FsrForce2 /= 30;
}
iForceSensorReading3 = analogRead(A3);//read little finger pressure
delay(30);
iForceSensorVoltage3 = map(iForceSensorReading3, 0, 1023, 0, 5000);
ulForceSensorConductance3 = conductanceFunction(ulForceSensorResistance3, iForceSensorVoltage3);
if (ulForceSensorConductance3 <= 1000)
{FsrForce3 = ulForceSensorConductance3 / 80;
}else
{FsrForce3 = ulForceSensorConductance3 - 1000;
FsrForce3 /= 30;
}
if (buttons) {
lcd.clear();
lcd.setCursor(0,0);
if (buttons & BUTTON_UP) {
lcd.print("Index Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_DOWN) {
lcd.print("Little Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce3,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_LEFT) {
lcd.print("Middle Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce1,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_RIGHT) {
lcd.print("Ring Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce2,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_SELECT) {
lcd.print("SELECT ");
lcd.setBacklight(WHITE);
}
}
}
// The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
// so FSR = ((Vcc - V) * R) / V
int conductanceFunction(long x, long y)
{long result;
x = 5000 - y; // fsrVoltage is in millivolts so 5V = 5000mV
x *= 10000; // 10K resistor
x /= y;
result = 1000000/x; //ulForceSensorConductance2 = 1000000 measured in micromhos
return result;
}
first likely issue, is this symptom sounds like a signed vs un-signed conflict. I see in your code the following calls
ulForceSensorConductance = conductanceFunction(ulForceSensorResistance, iForceSensorVoltage);
where
int conductanceFunction(long x, long y)
but
int iForceSensorVoltage;
You are passing an int(signed) into the second argument. Using it on math and creating a resultant variable of
long result;
and returning that as a INT.
Where you may have other problems.
You should follow some basic diagnostic procedures.
Assuming this problem is on ALL channels. if not then it is likely electrical.
Focusing on one channel.
PUT IN PRINTS of the various variables, to see what is moving as expected and validate the math is as expected

Resources