Attiny

I am building a metal detector from a project seen on the internet. It uses a Nano board and below is the code.
But I want to use an Attiny85 and obviously the code has to be changed
First I changed the port numbers and found it would not compile.
Then I changed the #define to const int.
Then it compiled but the project still would not work producing no buzzer output.
Is there anything else that I should change in the code to make it work on an Attiny 85
Thanks for any assistance
#define capPin A5
#define buz 9
#define pulsePin A4

#define led 10

long sumExpect=0; //running sum of 64 sums
long ignor=0; //number of ignored sums
long diff=0; //difference between sum and avgsum
long pTime=0;
long buzPeriod=0;

void setup()
{
Serial.begin(9600);
pinMode(pulsePin, OUTPUT);
digitalWrite(pulsePin, LOW);
pinMode(capPin, INPUT);
pinMode(buz, OUTPUT);
digitalWrite(buz, LOW);
pinMode(led, OUTPUT);
}

void loop()
{
int minval=1023;
int maxval=0;
long unsigned int sum=0;
for (int i=0; i<256; i++)
{
//reset the capacitor
pinMode(capPin,OUTPUT);
digitalWrite(capPin,LOW);
delayMicroseconds(20);
pinMode(capPin,INPUT);
applyPulses();

//read the charge of capacitor
int val = analogRead(capPin); //takes 13x8=104 microseconds
minval = min(val,minval);
maxval = max(val,maxval);
sum+=val;

long unsigned int cTime=millis();
char buzState=0;
if (cTime<pTime+10)
{
if (diff>0)
buzState=1;
else if(diff<0)
buzState=2;
}
if (cTime>pTime+buzPeriod)
{
if (diff>0)
buzState=1;
else if (diff<0)
buzState=2;
pTime=cTime;
}
if (buzPeriod>300)
buzState=0;

if (buzState==0)
{
digitalWrite(led, LOW);
noTone(buz);
}
else if (buzState==1)
{
tone(buz,2000);
digitalWrite(led, HIGH);
}

else if (buzState==2)
{
tone(buz,500);
digitalWrite(led, HIGH);
}
}

//subtract minimum and maximum value to remove spikes
sum-=minval;
sum-=maxval;

if (sumExpect==0)
sumExpect=sum<<6; //set sumExpect to expected value
long int avgsum=(sumExpect+32)>>6;
diff=sum-avgsum;
if (abs(diff)>10)
{
sumExpect=sumExpect+sum-avgsum;
ignor=0;
}
else
ignor++;
if (ignor>64)
{
sumExpect=sum<<6;
ignor=0;
}
if (diff==0)
buzPeriod=1000000;
else
buzPeriod=avgsum/(2*abs(diff));
}

void applyPulses()
{
for (int i=0;i<3;i++)
{
digitalWrite(pulsePin,HIGH); //take 3.5 uS
delayMicroseconds(3);
digitalWrite(pulsePin,LOW); //take 3.5 uS
delayMicroseconds(3);
}
}

#define capPin A5
#define buz 9
#define pulsePin A4
#define led 10

Those are not tiny85 pins.

Tiny85 pinout

What core are you using?

Read the how to use this forum-please read sticky to see how to properly post code. Remove useless white space and format the code with the IDE autoformat tool (crtl-t or Tools, Auto Format) before posting code.

Huh, well here's a piece of code in the wild that represents a place where planned optimizations would break code, suggesting I really shouldn't make "fast" digital I/O the default.... Good thing I never implemented them...

On the other hand, if they were assuming it took 0.5uS, they never tested that, because digitalWrite takes more like 3uS and change on a nano....

Either way, that timing needs to be adjusted, as the time for digitalWrite is not constant between different boards (the time is >95% the process of converting arduino pin numbers to port and bit; on the t85, I think I shortcircuit that because it only has one port, so it runs faster. Actually, maybe I don't - I should though, as the logic would be wasting flash space too)... Correct fix is fast digital I/O and a delay for the desired amount of time. This is on average a little longer than he does it for.... I would also think that it could be improved by choosing a delay that was optimized for the measured behavior of the assembled system. I'd want to know what sum and avgsum was when not detecting anything, and when detecting something.

PORTB|=(1<<(pin number)); // 2 clock cycles as long as pin number is compiletime known, 
// if not... I think 3, but then it's not interrupt safe on it's own (but this whole routine isn't interrupt safe
// since it's timing critical ANYWAY, so not relevant here, and he doesn't flip any bits on PORTB in
// an interrupt - or use interrupts for that matter - so doubly irrelevant. 
delayMicroseconds(6);
PORTB&=~(1<<(pin number));
delayMicroseconds(6);

There are many words for people who depend on any of the Arduino API calls running in a deterministic time, or a consistent time, even - but it's not polite to use them!

Also, not specific to t85, but he's running timing-critical code with interrupts enabled... and he runs it enough that he'll encounter artifacts from the millis() interrupt firing every time, and removing the max and min won't deal with as many as he will encounter per cycle AND the impact would be different depending on where in the cycle they fell... put cli(); on the line before applyPulses(); and sei(); on the line after the one starting with int val=, so the timing critical stuff is done without interrupts enabled; they're off for less than 1ms even with the slowass adc read in there so it's fine (though it pains me to be using analogRead there - you could use a dummy read in setup since that's the only pin you ever read to configure the ADC registers, then manually kick off the read, enable interrupts, then wait for the result... but it's not worth doing :stuck_out_tongue: ). But you do want the cli() and sei() there. I'll bet that would improve the readings on the nano.

Also, he should comment his code, like wtf is the purpose of what he's doing with pTime and cTime?!
And his style is vile - he does dirty (no {}'s) if and else if without indenting the conditionally executed line... Come on!

I think the code would benefit from a Ctrl+T autoformat, even though I don't always like what it does. I so wish I could tweak it in subtle and not-so-subtle ways.

I did say in my posting that I changed the port numbers to something acceptable?

Chris1960:
I did say in my posting that I changed the port numbers to something acceptable?

Well, please post the code you are actually using, not the code you started from! That way if you did something wrong in the course of modifying it, we can tell you! (I have actually seen this - more times than you want to know, too)

But, what I said still aplies (though the cheat with converting pin to bit number is tiny x5 only)

I really feel like this shouldn't have to be said, but it seems that it always does...

OT

I think the code would benefit from a Ctrl+T autoformat, even though I don't always like what it does. I so wish I could tweak it in subtle and not-so-subtle ways.

You can customize the autoformat to some extent:

This configuration file contains a selection of the available options provided by the formatting tool "Artistic Style"

Artistic Style

If you wish to change them, don't edit this file.

Instead, copy it in the same folder of file "preferences.txt" and modify the copy. This way, you won't lose your custom formatter settings when upgrading the IDE

If you don't know where file preferences.txt is stored, open the IDE, File -> Preferences and you'll find a link

2 spaces indentation

indent=spaces=2

also indent macros

indent-preprocessor

indent classes, switches (and cases), comments starting at column 1

indent-classes
indent-switches
indent-cases
indent-col1-comments

put a space around operators

pad-oper

put a space after if/for/while

pad-header

Move opening brackets onto new line

--style=allman --style=bsd --style=break -A1

delete empty lines in functions

--delete-empty-lines

Insert space padding around operators.

--pad-oper

Well, you learn something new every day. I have to make use of that! It looks like I could use the same tool with same options to autoformat my cores in a consistent manner too, with the same rules as my sketch. Spiffy!