It works on MEGA (Arduino), but it does not on Tiny?

Go To Last Post
23 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello guys!

 

I have created a program that works on Arduino, namely mega, but when uploaded on Tiny45, it does not work.

 

The general idea is to follow the data above HT and measure time how long we are above HT, if certain time has passed then turn on the led (ledState, toggle). However, if we wiggled our hand twice-fast enough (see below, it should be below 500) then we turn on the second led (ledState1, toggle).  Indeed there is fading in the first block of code as well, which only work if turned on the ledState1.

 

I am using the same sensor all along. Otherwise I am programming in Arduino IDE.

Please have a look at the code below and let me know, if you have any hints why this cannot be uploaded to tiny, what could be wrong?

 

Any help, suggestions, hints are very much appreciated!

 

Best.

 

//"first" hand 
if (Sensor.readProximity() > HT) {
    fadeUp = !fadeUp;  // fade rottation!
    startTime = millis();
    //elapsedTime = 0;
    while (Sensor.readProximity() > HT) {
      currentTime = millis();
      elapsedTime = currentTime - startTime;
      //FADING (between 500 and 2000)
      while (elapsedTime > 500 && A) {
        A = true;
        myFading();
        //Serial.print(elapsedTime); Serial.print("\t"); Serial.print("fadeUp:  ");
        //Serial.print(fadeUp); Serial.print("\t"); Serial.print("bri.:  "); Serial.print(brightness);
        elapsedTime = 0;
        //Serial.println(" YES led fading! We are between 500 and 2000 ms");
      }
    }
    if (elapsedTime > 10 && elapsedTime < 500) {
      ledState = !ledState;
      if (ledState1) {
        ledState = !ledState;
      }
      elapsedTime = 0;
    }
  }

//"second" hand
  if (Sensor.readProximity() < HT ) {
    startTime = millis();
    while (Sensor.readProximity() < HT) {
      currentTime = millis();
      elapsedTime = currentTime - startTime;
      //Serial.println(elapsedTime);
      if (elapsedTime > 500) {
        elapsedTime = 0;
        //Serial.println("... you missed the window");
        if (ledState1) {
          ledState1 = !ledState1;
        }
      }
      else if (elapsedTime > 10 && elapsedTime < 500) {
        ledState1 = !ledState1;
        A = true;
        //Serial.println(elapsedTimeS);
        elapsedTime = 0;
      }
    }
  }

 

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What kind of sensor is this?  I guess that it is an HC-SR04 type of proximity sensor, due to the reference to hand motions.

 

What kind of code is this?  Where's the setup(), loop(), and constructors?   Are the time values: currentTime , elapsedTime ,startTime  all declared unsigned long?

 

I recommend naming booleans after a question that references a descriptive state, beginning with the prefix "is-".   For example,  instead of just "A" for an undocumented boolean variable name, I  suggest  "isLastTestedElapsedTimeLowValue"  either TRUE or FALSE.  Sure these are long variable names, but that is what cut-and-paste is for.

 

When a program compiles and loads on the Mega, and then compiles and loads in the Tiny (I assume Tiny85 here) without major change, but doesn't run, then it could be references to peripherals on the Mega that aren't on the Tiny.   Or it could be that the Tiny85 is running at 8MHz (internal RC) or 1MHz (tiny85 factory clock setting) while the Mega is at 16MHz system clock.

Last Edited: Wed. Dec 5, 2018 - 01:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:

What kind of sensor is this?  I guess that it is an HC-SR04 type of proximity sensor, due to the reference to hand motions.

 

The sensor is vcnl4010.

 

Simonetta wrote:

What kind of code is this?  Where's the setup(), loop(), and constructors?   Are the time values: currentTime , elapsedTime ,startTime  all declared unsigned long?

 

Sorry, I did not post the setup(), however, what I have posted is exactly in the loop(); Yes, the currentTime... are all declared as unsigned long.

 

Simonetta wrote:

I recommend naming booleans after a question that references a descriptive state, beginning with the prefix "is-".   For example,  instead of just "A" for an undocumented boolean variable name, I  suggest  "isLastTestedElapsedTimeLowValue"  either TRUE or FALSE.  Sure these are long variable names, but that is what cut-and-paste is for.

 

Thanks! Will follow your suggestion.

 

Simonetta wrote:

When a program compiles and loads on the Mega, and then compiles and loads in the Tiny (I assume Tiny85 here) without major change, but doesn't run, then it could be references to peripherals on the Mega that aren't on the Tiny.   Or it could be that the Tiny85 is running at 8MHz (internal RC) or 1MHz (tiny85 factory clock setting) while the Mega is at 16MHz system clock.

 

Interesting thinking, I have tried to change the "speed" - via fuses, and it does not help... actually, it does not look that the "speed" is the question...

 

Best.

 

PS will rewrite the code and post back. 

 

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code seems to be based on millis(), so will be dependent on the clock source and speed of the clock.

Since the tiny is not directly supported by Arduino, what tiny "Core" are you using to add this support?

What does it say about how to setup the tiny for operation, in other words, how are the fuses supposed to be set for correct timing?

 

Some simple tests would be to run a test program (sketch) that blinks an LED and measure to see if the timing is correct.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jim!

Tiny core : https://github.com/SpenceKonde/ATTinyCore/blob/master/README.md. Ok?

I am compiling the code in Arduino, exporting hex and uploading via Avrfuses http://vonnieda.org/software/avrfuses, where I also set the fuses ... Ok?

Indeed, need to do the simple tests!

Best.

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess it is also important to use the appropriate pin assignments for timing opperations as for the PWM pins?

https://camo.githubusercontent.com/081b569122da2244ff7de8bae15eb56947d05cc8/687474703a2f2f6472617a7a792e636f6d2f652f696d672f50696e6f7574543835612e6a7067

Best

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello guys!

 

Just to let you know that I have sorted out the problem, at least it looks like that :) the clock, of course, is now on 8Mhz internal and it works on tiny, apparently there was an issue either with the first library, because I am using the other, however, I need to check that, in addition, I have cleaned the code and now I am using the above code via methods, so far so good. 

 

But now I am working on a different problem, namely I would like to reduce the size of the program. Indeed, I am using the "unsigned long" and several bools which is, if I am not wrong, very greedy in terms of memory, right? Anyway, is there a way to use a less greedy variable? I guess bool takes a memory of 2 bytes? 

 

While I read the prox of the sensor every time when it starts, I have realised that prox reading becomes stable only after 3-5 sec, a change of 1%-2%. Of course I could read prox again after the appropriate time, but I was wondering, how could I implement that in the main loop and make a really stable averaging? Any suggestions?

 

Best.

Bravo!!!

Last Edited: Fri. Dec 7, 2018 - 09:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How could anyone here possibly guess? - you haven't actually shown the program. Specifically you have not shown how variables such as currentTime/elapsedTime/etc are being declared.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are right, I will need to take some time and post the code :) sorry for not doing that already, thank you anyway. 

 

Best.

 

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello!

 

Below is the code that I am successfully using to measuring time when threshold is either above .

 

It works on tiny45, however, due to the return it does that only once until called again...

 

Is there a way to return a value and continue? Actually, I am not really sure, if the return is the right way to use it here...

 

Any comments are more than welcome!

 

Best.

 

// ok time above HT
unsigned long timeAboveHT() {
  uint16_t myProx = Sensor.getProximity();
  //measure time change to a method that returns elapsed time!
  elapsedTime = 0;
  if (myProx > HT) {
    // fadeUp = !fadeUp;  //fade Rotation
    startTime = millis();
    //elapsedTime = 0;
    while (Sensor.getProximity() > HT) {
      currentTime = millis();
      elapsedTime = currentTime - startTime;
      //Serial.println(elapsedTime);
    }
  }
  return elapsedTime;
}

 

 

 

 

 

 

 

 

 

 

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mu234 wrote:
Is there a way to return a value and continue? Actually, I am not really sure, if the return is the right way to use it here...
You haven't shown enough context - surely it's the place where you CALL this timeAboveHT() where you have some kind of "processing loop"?

 

(and yes - passing data to/from functions is the "smart strategy" - it then makes the function individually testable as there are defined inputs/outputs that can be provided or tested)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am calling this method in the main loop:

 

 if (timeAboveHT() < 500) {
    ledState = !ledState;
  }

afterwards I make a decision with regard the led state:

 

if(ledState){
    analogWrite(ledPin, 255);
}

It works, however, I want to print out the ledState, it only returns at each step, which is ok, but how print the ledState endlessly? 

 

Best.

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Again you are not showing enough context.

 

But just a tip for the future - don't just sit down and start typing C and making up the design as you go along as you will very likely hit this kind of thing where "I have this value here but I need it over there" or similar. What you should do is design the flow of the software at the highest level first away from the actual C. Picture the sequence in which things will happen and so on. When you have that clear picture in your mind then sit down to actually implement the software and you will have a much more structured design.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mu234 wrote:
But now I am working on a different problem, namely I would like to reduce the size of the program. Indeed, I am using the "unsigned long" and several bools which is, if I am not wrong, very greedy in terms of memory, right? Anyway, is there a way to use a less greedy variable? I guess bool takes a memory of 2 bytes? 

 

Well, you can try to replace bool (and any other variable that you know will only have values up to 255) by uint8_t. But this will only save a few bytes at best.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As the (modern) AVRs have GPIOR0 which is an SBI/CBI register I would tend to cast my 8 most used "bools" onto the 8 bits in the register. Something like:

#include <avr/io.h>

typedef struct {
	int valve:1;
	int leftLED:1;
	int rightLED:1;
	int countingUp:1;
	int online:1;
	//etc.
} mybools_t;

#define boolvars (*(volatile mybools_t *)&GPIOR0)

int main(void) {
	boolvars.valve = 0;
	boolvars.countingUp = 1;
	boolvars.online = 1;
}

When I build that I get:

	boolvars.valve = 0;
  80:	f0 98       	cbi	0x1e, 0	; 30
	boolvars.countingUp = 1;
  82:	f3 9a       	sbi	0x1e, 3	; 30
	boolvars.online = 1;
  84:	f4 9a       	sbi	0x1e, 4	; 30

which is tight as you can possibly get and it's not actually using any "RAM" as such. For your next 16 "bools" you can do the same with GPIOR1 and GPIOR2 but they are less efficient:

	boolvars.valve = 0;
  80:	8b b5       	in	r24, 0x2b	; 43
  82:	8e 7f       	andi	r24, 0xFE	; 254
  84:	8b bd       	out	0x2b, r24	; 43
	boolvars.countingUp = 1;
  86:	8b b5       	in	r24, 0x2b	; 43
  88:	88 60       	ori	r24, 0x08	; 8
  8a:	8b bd       	out	0x2b, r24	; 43
	boolvars.online = 1;
  8c:	8b b5       	in	r24, 0x2b	; 43
  8e:	80 61       	ori	r24, 0x10	; 16
  90:	8b bd       	out	0x2b, r24	; 43

If you are using an "old school" AVR that does not have GPIOR0 such as mega16/32 then pick an 8 bit R/W register that is not being used for anything else. TWAR is a good starting point if you don't use the I2C. If I build 

#define boolvars (*(volatile mybools_t *)&TWAR)

int main(void) {
	boolvars.valve = 0;
	boolvars.countingUp = 1;
	boolvars.online = 1;
}

for mega16 then again I get:

	boolvars.valve = 0;
  6c:	10 98       	cbi	0x02, 0	; 2
	boolvars.countingUp = 1;
  6e:	13 9a       	sbi	0x02, 3	; 2
	boolvars.online = 1;
  70:	14 9a       	sbi	0x02, 4	; 2

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for this, looks impressive!

Is it possible that due to the use of other library the code takes less memory?

Best.

Bravo!!!

Last Edited: Tue. Dec 11, 2018 - 07:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look yourself. You can't get shorter than one 16bit SBI or CBI opcode and you can't get faster than the one cycle it takes to execute and, as I said before, this is using SFRs not RAM so this truly is the most efficient solution possible for using eight one bit state variables. The only downside of mega AVR is that it only has one GPIO register in range of the SBI/CBI opcodes. It's not until you get to Xmega where they give you 16 (actually, possibly too many, it could have done with 8 and two more VPORTs).
.
For Mega the Codevision compiler is arguably better than the others (like GCC) as it has a facility to put some of the 32 CPU registers off to one side for this same purpose then the set/clear single bit in register opcodes can be used to make equally efficient state variables.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OP is using a Tiny45, right?  This one has three GPIOR's in range of SBI/CBI.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh nice - far better than the original chips that delivered GPIORn (mega48/88/168 (and hence later the 328 too)) that only put GPIOR1 and GPIOR2 in range of IN/OUT with only GPIOR0 in range of SBI/CBI.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all!

 

I have put some code together, have a look. Somehow I cannot get this library going properly ( https://github.com/SV-Zanshin/VC... ). Namely , I am having problems with setting the threshold... While I have been trying also this library ( https://adafruit.github.io/Adafr... ) it apparently works better, but the down size is there is no support for the interrupt on VCNL. So, I am wondering, can I use one library for reading prox, while other for interrupt? I know this is stupid and it will take more memory... however, it will work?

 

Anyway, below is the code for the basic test of proximity, with the setT() I want to make the setting of the high threshold (HT), which should be 3% over the getProximity() , but does it work? Are the variable declared properly, will the sensor provide me this number? I do not have a debugging on tiny, so I cannot see what is going on, anyway, when I run the code on my breadboard , the main led is lid, without even getting close to the sensor. 

PS the library is available at GitHub, however, I have port this library to tiny, which I am using in a local sketch... I am attaching the .cpp and .h

 

And yes, I am still going back to the initial question, why it works on Arduino and does not on tiny? BTW it compiles...

 

//#include <Adafruit_VCNL4010.h> //working library // https://adafruit.github.io/Adafruit_VCNL4010/class_adafruit___v_c_n_l4010.html
#include <TinyWireM.h>        //global library search
#include "Tiny_VCNL4010.h"    //local library search

//Adafruit_VCNL4010 Sensor;
VCNL4010 Sensor;

const byte ledPin = 1;
const byte ledSigPin = 4;  

//SENSOR THRESHOLDS
uint16_t HT;

void setup() {

  pinMode(ledPin, OUTPUT);
  pinMode(ledSigPin, OUTPUT);

  startVCNL();

  setT();

  analogWrite(ledSigPin, 255);

}

void loop() {  

  if(Sensor.getProximity() > HT){
    analogWrite(ledPin, 255);
  }
  else if(Sensor.getProximity() < HT){
    analogWrite(ledPin, 0);
  }
}

 

 

// set the thresholds
void setT() {

  static uint16_t offSet;
  static uint16_t percentage;

  percentage = 103;

  offSet = Sensor.getProximity();

  HT = ( (offSet / 100) * percentage );  

}

 

// https://github.com/SV-Zanshin/VCNL4010
// function to initialize the sensor
void startVCNL() {
  //Serial.println(F("Starting VCNL4010 "));
  // Loop until sensor found
  while (!Sensor.begin()) {
    //Show error message
    //Serial.println(F("Error, unable to find or identify VCNL4010."));
    // Wait 2 seconds before retrying
    delay(2000);
  } // of if-then we can't initialize or find the device

  // Boost power to Proximity sensor
  //  20 mA = DEFAULT,
  //  LED Current is limited to 200 mA for values higher.
  Sensor.setLEDmA(200);

  // Sample 128x per second
  //  000 - 1.95 measurements/s (DEFAULT)
  //  001 - 3.90625 measurements/s
  //  010 - 7.8125 measurements/s
  //  011 - 16.625 measurements/s
  //  100 - 31.25 measurements/s
  //  101 - 62.5 measurements/s
  //  110 - 125 measurements/s
  //  111 - 250 measurements/s
  Sensor.setProximityHz(62.5);     // Sample 128x per second           //

  // Set frequency:
  //  00 = 390.625 kHz (DEFAULT) = 0
  //  01 = 781.25 kHz            = 1
  //  10 = 1.5625 MHz            = 2
  //  11 = 3.125 MHz             = 3
  Sensor.setProximityFreq(0);

  //Set ambient
  //Sensor.setAmbientLight(2, 128);

  // Continuously sample proximity using frequency and averaging settings
  Sensor.setProximityContinuous(true);

  // Turn off continousl ALS reading due to power consumption
  Sensor.setAmbientContinuous(false);
}

 

 

 

 

Attachment(s): 

Bravo!!!

Last Edited: Wed. Dec 12, 2018 - 08:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@MU234 - What problems are you having with the https://github.com/SV-Zanshin/VC... library? If it is a bug, perhaps it can be fixed quickly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, no problems when using with At Tiny, but when on Arduino I am having problems with using/starting the library... anyway, I am using the Adafruit to do that... Thank you.

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello All!

 

I am using the sensor and when the reading is above threshold the time is measured, I am also measuring the time below threshold, namely HT. Afterwards, I am using this timings to decide... but, I have noticed that the if() is not working every time ? For example, when I am debugging the "timing" functions I get the timings ok, but the if() just ignores the timings? Interestingly not every time... Is this the problem of mills(), should rather micros() be used?

Anyway, am I doing, measuring, passing data properly, the right way? Is it something else wrong, maybe I am not measuring the time with the timeAboveHT() and timeBelowHT() properly? Anyway, I have attached the code, see below..

 

The main loop :

 


  if ( timeAboveHT() > 10 && timeAboveHT() < 100 && timeBelowHT() > 500 ) {
    ledState = !ledState;
    Serial.print("ledState: "); Serial.println(ledState);
    if (ledState) {
      brightness = 50;
      fadeIn();
    }
    else if (!ledState) {
      fadeOut();
    }

  }

 

 

Functions used...

 

//get the time above threshold
unsigned long timeAboveHT() {
  if (Sensor.readProximity() > HT) {
    elapsedTime = 0;
    //elapsedTime = 0;
    startTime = millis();
    //elapsedTime = 0;
    //if (startTime > 150) {
    while (Sensor.readProximity() > HT) {
      currentTime = millis();
      elapsedTime = currentTime - startTime;
      //Serial.print("TAHT:  "); Serial.println(elapsedTime);
      //start fading if the elapsedTime is above 1 sec
      if (elapsedTime > 1000) {
        myFading();
      }
    }
  }
  //Serial.print("t A HT: "); Serial.println(elapsedTime);
  return elapsedTime;
}

//get the time below threshold
unsigned long timeBelowHT() {
  if (Sensor.readProximity() < HT) {
    elapsedTime = 0;
    startTime = millis();
    while (Sensor.readProximity() < HT) {
      currentTime = millis();
      elapsedTime = currentTime - startTime;
      //Serial.print("*        TBHT:  "); Serial.println(elapsedTime);
      if (elapsedTime > 550) {
        //Serial.println(elapsedTime);
        return elapsedTime;
      }
    }
  }
  return elapsedTime;
}

 

Any suggestions, ideas are more than welcome!

 

Best.

 

 

 

Bravo!!!