Pages: [1]   Go Down
Author Topic: Uncalled function stops program from running?  (Read 971 times)
0 Members and 1 Guest are viewing this topic.
Arduinoville
Offline Offline
Newbie
*
Karma: 1
Posts: 26
Arduino is my strong friend
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am running into a strange problem...

I have a working code to read a sensor and write to an SD card. Now I want to write something to a register on the sensor, so I wrote a function that should do so. HOWEVER, with that function in the code, even when the function is not called at all, the program executes the first few lines of code in setup() and returns back to the first line!?

I am baffled at why this additional function, which is not called within setup() or loop() at all would cause the program to act differently. Help please?

Thanks
Logged

Sometimes things are as they appear

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26488
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Guess what - we're baffled too, but at least you can read the sketch.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Arduinoville
Offline Offline
Newbie
*
Karma: 1
Posts: 26
Arduino is my strong friend
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Good hint...

Here is the sketch in its entirety (continued in next post). The function causing the problem is setRegister(), at the very bottom. I am looking to call this in the loop(), but it is commented out now.

Code:
/*
 ADIS 16367 Logger
 
 Creates bit-banged SPI implementation for ADIS16367
 This is able to use readAllToString() which reads
 data from sensor, writes to string, and prints it
 once the buffer has been filled
 
 It does so using an interrupt triggered by Timer1
 
 Writes to SD card once there has been a sufficient
 number of samples to fill the buffer.
 
 It requires a file CONFIG.TXT to exist in the root
 directory of the SD card. It must contain 3 numbers
 the delay time (s), sampling frequency (1/s), and
 recording time (s) in that order. All other characters
 in the file are ignored.
 
 Circuit:
 Arduino          ->   ADIS 16367
 IRQ: pin 4         ->  DIO1: pin 7
 CS: pin 7          ->  CS: pin 6
 DI/MOSI: pin 3     ->  DIN: pin 5
 DOUT/MISO: pin 5   ->  DOUT: pin 4
 SCLK: pin 2        ->  SCLK: pin 3
 
 Arduino          ->    SD Card
 MOSI: pin 11       ->  DI
 MISO: pin 12       ->  DO
 SCK: pin 13        ->  SCK
 CS: pin 10         ->  CS
 
 created 22 Feb 2011
 modified 22 Feb 2011
 by Matt Harding
 
 Thank you to:
 Bill Greiman for his SdFat library
 http://code.google.com/p/sdfatlib/
 Jesse Tane for the Timer1 library
 http://perfectverse.com/jesse/portfolio/projects/timerOne/index.html
 Sebastian Tomczak for his "SPI by Hand" example
 http://little-scale.blogspot.com/2007/07/spi-by-hand.html
 */

#include <SdFat.h>
#include <SdFatUtil.h>
#include "TimerOne.h"

unsigned int fs = 10;
unsigned long time = 5;
const unsigned int sample_size = 42;
unsigned int samples_per_block = 512/sample_size;
unsigned long delaytime = 5;

// counters and data strings
volatile unsigned int samplecounter = 0;
volatile unsigned int counter = 0;

// data strings
volatile char dataString[512];
uint8_t* pCache;

// IMU pins
const byte dataReadyPin = 4;
const byte chipSelectPin = 7;
const byte mosiPin = 3;
const byte misoPin = 5;
const byte sclkPin = 2;
const byte SDcs = 10;


Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
SdFile configfile;

uint32_t bgnBlock, endBlock;

//// store error strings in flash to save RAM
//#define error(s) error_P(PSTR(s))

void error_P(const char* str) {
  Serial.print("error: ");
  Serial.println(str);
  if (card.errorCode()) {
    Serial.print("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}

//Sensor's memory register addresses:
const byte SUPPLY_OUT = 0x02;    // Power supply reading
// a bunch of defines are omitted here…

//Sensor commands
const byte READ = 0b00000000;     // ADIS16367 read command (2 bytes)
const byte WRITE = 0b10000000;   // ADIS16367 write command
const byte BURST_READ = 0x3E;  // ADIS16367 burst read command

void setup() {
  // Setup communications
  Serial.begin(115200);

  Serial.flush();
  Serial.println("Type any character to start");
  while (!Serial.available());

  // Initialize ADIS SPI bus
  SPIbegin(chipSelectPin);

  // Initialize SD card
  unsigned long start = millis();

  pinMode(SDcs, OUTPUT);
  digitalWrite(SDcs, LOW);
  // initialize the SD card at SPI_FULL_SPEED for best performance.
  // try SPI_HALF_SPEED if bus errors occur.
  if (!card.init(SPI_FULL_SPEED)) error_P(PSTR("card.init failed"));

  start = millis() - start;

  Serial.print("Card init time: ");
  Serial.print(start);
  Serial.println(" millis");

  // initialize a FAT volume
  if (!volume.init(&card)) error_P(PSTR("volume.init failed"));

  // open the root directory
  if (!root.openRoot(&volume)) error_P(PSTR("openRoot failed"));
}
Logged

Sometimes things are as they appear

Arduinoville
Offline Offline
Newbie
*
Karma: 1
Posts: 26
Arduino is my strong friend
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That was the header stuff and the setup()

Here is the loop()
Code:
void loop() {
  char nextchar;
  // Look for configuration file
  if (configfile.open(&root, "CONFIG.TXT", O_READ)) {
    Serial.println("Reading configuration file...");

    delaytime = 0;
    nextchar = configfile.read();
    while(nextchar>='0' && nextchar<='9') {
      delaytime = delaytime*10 + (nextchar-'0');
      nextchar = configfile.read();
    }
    while(nextchar<='0' || nextchar>='9') {
      nextchar = configfile.read();
    }


    fs = 0;
    while(nextchar>='0' && nextchar<='9') {
      fs = fs*10 + (nextchar-'0');
      nextchar = configfile.read();
    }
    while(nextchar<='0' || nextchar>='9') {
      nextchar = configfile.read();
    }


    time = 0;
    while(nextchar>='0' && nextchar<='9') {
      time = time*10 + (nextchar-'0');
      nextchar = configfile.read();
    }
    configfile.close();
  }
  else if(configfile.open(&root, "config.txt", O_READ)) {
    Serial.println("Reading configuration file...");

    delaytime = 0;
    nextchar = configfile.read();
    while(nextchar>='0' && nextchar<='9') {
      delaytime = delaytime*10 + (nextchar-'0');
      nextchar = configfile.read();
    }
    while(nextchar<='0' || nextchar>='9') {
      nextchar = configfile.read();
    }


    fs = 0;
    while(nextchar>='0' && nextchar<='9') {
      fs = fs*10 + (nextchar-'0');
      nextchar = configfile.read();
    }
    while(nextchar<='0' || nextchar>='9') {
      nextchar = configfile.read();
    }


    time = 0;
    while(nextchar>='0' && nextchar<='9') {
      time = time*10 + (nextchar-'0');
      nextchar = configfile.read();
    }
    configfile.close();
  }
  else {
    Serial.println("No CONFIG.TXT found, using default values");
  }

  // Display recording data
  Serial.print("delay time (s) = ");
  Serial.println(delaytime);
  Serial.print("fs (sps) = ");
  Serial.println(fs);
  Serial.print("time (s) = ");
  Serial.println(time);
  Serial.print("sample size (chars) = ");
  Serial.println(sample_size);
  Serial.print("samp/block = ");
  Serial.println(samples_per_block);
  unsigned int block_count = (fs*time)/samples_per_block;
  Serial.print("blocks = ");
  Serial.println(block_count);

  // Begin Delay
  Serial.println("Beginning delay...");
  delay(delaytime*1000);
  Serial.println("Delay completed");

  // Send command to set gyro range to +/- 1200 deg/s
  Serial.println("Set range to +/- 1200 deg/s");
  byte whichBits[] = {2,1,0};
  byte setToWhat[] = {1,0,0};
//  setRegister(SENS_AVG,HIGH,whichBits,setToWhat);
//  Serial.println("Set Bartlett filter to 4 taps");
//  setRegister(SENS_AVG,LOW,whichBits,setToWhat);
  Serial.println("Configuration Complete!");
 
 
  // Set up file to write
  char filename[] = "DATA00.TXT";
  byte filenum = 0;
  while (file.open(&root, filename, O_READ)) {
    file.close();
    filenum++;
    filename[4] = (filenum/10)+'0';
    filename[5] = (filenum%10)+'0';
  }


  // Create a contiguous file
  if (!file.createContiguous(&root, filename, 512UL*block_count)) {
    error_P(PSTR("createContiguous failed"));
  }
  // Get the location of the file's blocks
  if (!file.contiguousRange(&bgnBlock, &endBlock)) {
    error_P(PSTR("contiguousRange failed"));
  }
  //*********************NOTE**************************************
  // NO SdFile calls are allowed while cache is used for raw writes
  //***************************************************************

  // Clear the cache and use it as a 512 byte buffer
  //  uint8_t* pCache = volume.cacheClear();
  pCache = volume.cacheClear();

  // Fill cache with samples_per_block lines
  for(int i = 0 ; i<512 ; i++) {
    dataString[i] = ' ';
    pCache[i] = ' ';
  }
  // Loop through each sample
  for (int i = 0 ; i < 512-sample_size; i += sample_size) {
    // And put newline/carriage return at end of line
    dataString[i] = '\r';
    dataString[i+1] = '\n';
  }
  dataString[511] = '\0';   //EOF end of file character must end each string
  pCache[511] = '\0';   //EOF end of file character must end each string



  Serial.print("Start raw write of ");
  Serial.print(file.fileSize());
  Serial.println(" bytes at");

  Serial.print((512UL*block_count)/time);
  Serial.println(" bytes per second");

  Serial.print("to ");
  Serial.println(filename);

  Serial.print("Please wait ");
  Serial.print(time);
  Serial.println(" seconds");

  // tell card to setup for multiple block write with pre-erase
  if (!card.erase(bgnBlock, endBlock)) error_P(PSTR("card.erase failed"));
  if (!card.writeStart(bgnBlock, block_count)) {
    error_P(PSTR("writeStart failed"));
  }

  // Init stats
  unsigned int maxWriteTime = 0;
  unsigned long start = millis();
  unsigned long writeTime = 0;

  // Start Timer1
  Timer1.initialize((1000000UL/fs)); // Start timer at fs Hz
  // Attach timer interrupt
  Timer1.attachInterrupt(isr);

  while( (millis()-start) < (time*1000) ) {
    if (samplecounter==samples_per_block) {
      samplecounter = 0;
      // Write a 512 byte block
      writeTime = micros();
      if (!card.writeData(pCache)) {
        error_P(PSTR("writeData failed"));
        while(1);
      }
      writeTime = micros() - writeTime;
      // Check for max write time
      if (writeTime > maxWriteTime) {
        maxWriteTime = writeTime;
      }
    }
  }

  // Stop the interrupt
  Timer1.detachInterrupt();

  // End multiple block write mode
  if (!card.writeStop()) error_P(PSTR("writeStop failed"));

  Serial.println();
  Serial.println("Done");

  Serial.print("Elapsed time: ");
  Serial.print(millis()-start);
  Serial.println(" millis");

  Serial.print("Max write time: ");
  Serial.print(maxWriteTime);
  Serial.println(" micros");

  // Close files for next pass of loop
  root.close();
  file.close();
  Serial.println();

  // All done, stop here
  while(1);
}

Logged

Sometimes things are as they appear

Arduinoville
Offline Offline
Newbie
*
Karma: 1
Posts: 26
Arduino is my strong friend
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

And here is all the other functions with the setRegister() function at the bottom.
Code:


void isr() {
  readAllToString();
  samplecounter++;
  // This check will skip the block if the SD
  //    card is not done writing
  if(samplecounter==samples_per_block){
    strlcpy((char*)pCache,(char*)dataString,samples_per_block*sample_size+1);
  }
}



//Sends a read command to the ADIS16367:
int readRegister(byte thisRegister ) {
  int result = 0;   // result to return
  bitClear(PORTD,chipSelectPin);
  // ADIS16367 expects the register address in the lower 7 bits
  // now combine the register address and the command into one byte:
  byte dataToSend = thisRegister | READ;
  // take the chip select low to select the device:
  while(bitRead(PIND,dataReadyPin));
  //  while(digitalRead(dataReadyPin)); //Wait if the pin is low
  // send the device the register you want to read: 
  SPItransfer2(dataToSend,0);
  delayMicroseconds(4);
  result = SPItransfer2(0,0);
  bitSet(PORTD,chipSelectPin);
  // return the result:
  return(result);
}


void writeRegister(byte reg, byte data) {
  bitClear(PORTD,chipSelectPin);     // Select device
  SPItransfer2(reg|WRITE,data);      // Writes data to register
  bitSet(PORTD,chipSelectPin);       // Deselect device
}


// Transfer 2 bytes via SPI and combine the results
// into a 16 bit int
int SPItransfer2(byte data1, byte data2) {
  int result = SPItransfer(data1)<<8;
  result |= SPItransfer(data2);
  return(result);
}

// Transfer a single byte via SPI
byte SPItransfer(byte data) {
  // SCK begins high
  for(byte bit=0 ; bit<8 ; bit++) {
    bitClear(PORTD,sclkPin); // SCK fall low
    bitWrite(PORTD,mosiPin,(data>>7) & 0x01); // Write data to MOSI pin
    data = data << 1;
    bitSet(PORTD,sclkPin); // SCK rise high
    data |= bitRead(PIND,misoPin); // read data from MISO pin
  }
  return(data);
}



// Read all registers and write to string
// String begins with new line (0-1)
// Time takes 6 hex chars (2-7)
// Each of gyro/acc takes 4 hex chars, 14 bits (8-11,12-15,16-19...8+i*5-8+i*5+3)
// Auxilary ADC takes 3 hex chars, 12 bits (39-41)
void readAllToString(void) {
  // take the chip select low to select the device
  bitClear(PORTD,chipSelectPin);
  //Wait if the pin is low
  while(bitRead(PIND,dataReadyPin));
  addhexchar(dataString, millis(), 2 + (samplecounter*sample_size),6);
  // Get time and write to string
  SPItransfer2(XGYRO_OUT,0); // Ask for X Gyro
  int data = SPItransfer2(YGYRO_OUT,0); // Get X Gyro and ask for Y Gyro
  addhexchar(dataString, data&0x3FFF, 9+(0*5) + (samplecounter*sample_size),4);
  // Save to text string
  data = SPItransfer2(ZGYRO_OUT,0);     // Get Y Gyro and ask for Z Gyro
  addhexchar(dataString, data&0x3FFF, 9+(1*5) + (samplecounter*sample_size),4);
  // Save to text string
  data = SPItransfer2(XACCL_OUT,0);     // Get Z Gyro and ask for X Acc
  addhexchar(dataString, data&0x3FFF, 9+(2*5) + (samplecounter*sample_size),4);
  // Save to text string
  data = SPItransfer2(YACCL_OUT,0);     // Get X Acc and ask for Y Acc
  addhexchar(dataString, data&0x3FFF, 9+(3*5) + (samplecounter*sample_size),4);
  // Save to text string
  data = SPItransfer2(ZACCL_OUT,0);     // Get Y Acc and ask for Z Acc
  addhexchar(dataString, data&0x3FFF, 9+(4*5) + (samplecounter*sample_size),4);
  // Save to text string
  data = SPItransfer2(AUX_ADC,0);       // Get Z Acc and ask for Aux ADC
  addhexchar(dataString, data&0x3FFF, 9+(5*5) + (samplecounter*sample_size),4);
  // Save to text string
  data = SPItransfer2(0,0);             // Get Aux ADC
  addhexchar(dataString, data&0xFFF, 39 + (samplecounter*sample_size),3);
  // Save to text string
  // Pull chip select HIGH to delect
  bitSet(PORTD,chipSelectPin);
}




void SPIbegin(byte CSpin) {
  // Set correct pin modes
  pinMode(dataReadyPin, INPUT);
  pinMode(CSpin, OUTPUT);
  pinMode(mosiPin,OUTPUT);
  pinMode(misoPin,INPUT);
  pinMode(sclkPin,OUTPUT);
  //Clock polarity in mode 3 is high
  digitalWrite(sclkPin,HIGH);
  //Set chip select low to activate device
  digitalWrite(CSpin, HIGH);
}



// creates char[] from int in hex with digits chars
void addhexchar(volatile char* c, unsigned long n, int start, int digits)
{
  byte nextchar;
  for(int ii=0; ii<digits ; ii++) {
    nextchar = (n >> (digits-ii-1)*4) & 0xf;
    if(nextchar<=9) {
      c[start+ii] = '0' + nextchar;
    }
    else {
      c[start+ii] = 'A' + nextchar-10;
    }
  }
}



// Sends commands to set a given register
void setRegister(int reg, boolean highOrLow, byte* whichBits, byte* setTo) { 
  byte n=sizeof(whichBits);
  delay(500);
  // Read in data from register
  int regdata;
  if(highOrLow==HIGH) {
    regdata = highByte(readRegister(reg));
  }
  else {
    regdata = lowByte(readRegister(reg));
  }
  Serial.print("Register contains: ");Serial.println(regdata,BIN);
 
  // Set or clear bits as needed
  byte working = regdata;
  for (int ii=0 ; ii<n ; ii++) {
    if(setTo[ii]==1) {
      bitSet(working,whichBits[ii]);
    }
    else {
      bitClear(working,whichBits[ii]);
    }
  }
  Serial.print("Writing: ");Serial.println(working,BIN);
 
  //Write to register
  if(working!=regdata) {
    writeRegister(reg+highOrLow,working);
  }
  else {
    Serial.println("Register already set correctly");
  }
  delay(100);
  asdf
  //Check if it's right!
  regdata = readRegister(reg);
  if(highOrLow==HIGH) {
    regdata = highByte(regdata);
  }
  else {
    regdata = lowByte(regdata);
  }
 
  if(regdata==working) {
    Serial.println("Successful");
  }
  else {
    Serial.print(regdata,BIN);
    Serial.println(" fail...");
  }
  delay(500);
}

Logged

Sometimes things are as they appear

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26488
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This isn't your problem, but will cause you one later:
Code:
void setRegister(int reg, boolean highOrLow, byte* whichBits, byte* setTo) {  
  byte n=sizeof(whichBits);

is the same as writing:
Code:
byte n=2;
I'm guessing you don't want that.

Otherwise, try removing some Serial prints, or use PROGMEM for constant strings.
« Last Edit: March 10, 2011, 01:48:31 pm by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Arduinoville
Offline Offline
Newbie
*
Karma: 1
Posts: 26
Arduino is my strong friend
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Interesting catch. I thought sizeof() gave you the number of bytes in whatever argument you provide. So if I use
Code:
byte whichBits[] = {2,1,0};
wouldn't
Code:
byte n=sizeof(whichBits);
return 3, since whichBits has three 1-byte values in it?
Logged

Sometimes things are as they appear

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26488
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

But in setRegister, whichBits is not an array, it is a pointer.
Code:
void setRegister(int reg, boolean highOrLow, byte* whichBits, byte* setTo)
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Arduinoville
Offline Offline
Newbie
*
Karma: 1
Posts: 26
Arduino is my strong friend
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll admit, that is something I'm a bit fuzzy on. Would
Code:
void setRegister(int reg, boolean highOrLow, byte whichBits[], byte setTo[]) { 
declare it as an array, giving me the number of items in the array with sizeof()?

Also, I just removed all the Serial.print statements from the setRegister() function... and it seems to do the trick!!! That is not something I would have ever thought of. Do you have any insight on why that causes the hang up?
Logged

Sometimes things are as they appear

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26488
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The array declaration is identical to the pointer declaration.
You need to pass in the size.

Your prints use strings which consume RAM.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Arduinoville
Offline Offline
Newbie
*
Karma: 1
Posts: 26
Arduino is my strong friend
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Brilliant! Thank you!
Logged

Sometimes things are as they appear

Pages: [1]   Go Up
Jump to: