News:

SMF for DIYStompboxes.com!

Main Menu

ATtiny85 code issues

Started by patrick398, September 09, 2020, 06:24:12 AM

Previous topic - Next topic

patrick398

Yes i did think that just after i sent my last message so i tried with the RC filter on the stompLFO output and all it did was make the LED blink a lot less. It seemed to turn off a lot less. Also no difference without the RC filter.

potul

You need a low pass filter after the stomplfo because it uses PWM to generate the different voltages.
You don't need a lpf after the arduino, as it only generates a square signal (0 or Vcc).
You need to choose the right values so that you are filtering your pwm frequency, but still allowing your desired frequencies to pass.

patrick398

Quote from: potul on September 14, 2020, 04:37:05 PM
You need a low pass filter after the stomplfo because it uses PWM to generate the different voltages.
You don't need a lpf after the arduino, as it only generates a square signal (0 or Vcc).
You need to choose the right values so that you are filtering your pwm frequency, but still allowing your desired frequencies to pass.

With the filtering after the stompLFO it's the same issue of going out of time. I'm using 10k>47n>100k>4n7, caps to ground, as suggested by the stompLFO docs.

I'm starting to think this might be the wrong approach.

In my head what i want to do actually seems quite straight forward. There is an existing tap tempo circuit controlling another circuit. I want to read the output of this tap tempo (which is putting out roughly 4v pulses). The arduino input pin will read the existing tap tempo output, when it is HIGH, it will output an arduino pin HIGH, when the input is LOW it will output that pin LOW.

I need to calculate the tempo of the incoming pulses so i guess i would use pulseIn to measure the 'high time' of the input, and pulseIn to measure the 'low time of the input'. Adding them together would give me the period.

I then need to apply a delay somehow to the output, so that it falls exactly on the off beat. I guess the length of this delay would be equal to 'high time' or 'low time' since that's half of the period.

Anyway, here is a sketch i threw together quickly. For now i have ignored the delay aspect. It's probably completely wrong but maybe it's a better starting point...


int input = 12;
int output = 11;
unsigned long highTime;
unsigned long lowTime;
unsigned long period;
unsigned long time;


void setup() {
  pinMode (input, INPUT_PULLUP);
  pinMode (output, OUTPUT);

}

void loop() {

  time = millis();
  highTime = pulseIn (input, HIGH); // read time input is high
  lowTime = pulseIn (input, LOW); // read time input is low
  period = (highTime + lowTime); // period is equal to high time plus low time

  digitalRead (input); // read input pin
  if (input == HIGH) { // if input pin is high write output pin high
    digitalWrite (output, HIGH);

  }

  digitalWrite (output, LOW); // write output pin low

}

ElectricDruid

Quote from: patrick398 on September 15, 2020, 05:26:23 AM
With the filtering after the stompLFO it's the same issue of going out of time. I'm using 10k>47n>100k>4n7, caps to ground, as suggested by the stompLFO docs.

That should be fine.

Quote
In my head what i want to do actually seems quite straight forward. There is an existing tap tempo circuit controlling another circuit. I want to read the output of this tap tempo (which is putting out roughly 4v pulses). The arduino input pin will read the existing tap tempo output, when it is HIGH, it will output an arduino pin HIGH, when the input is LOW it will output that pin LOW.

Yep, that seems simple, and wouldn't even really need any timing. Just read it, output it, done. Go round the loop, do it again. Keep doing it until someone pulls the power.

Quote
I need to calculate the tempo of the incoming pulses so i guess i would use pulseIn to measure the 'high time' of the input, and pulseIn to measure the 'low time of the input'. Adding them together would give me the period.

I then need to apply a delay somehow to the output, so that it falls exactly on the off beat. I guess the length of this delay would be equal to 'high time' or 'low time' since that's half of the period.

If you just want a square wave that's half-a-wavelength out of phase, that's the same as 180 degrees out of phase - e.g. inverted. Instead of trying to delay it, just read the input state, and then output the inverse. It'll give you the same effect without the messing around.


patrick398

Quote from: ElectricDruid on September 15, 2020, 01:48:48 PM

Quote
I then need to apply a delay somehow to the output, so that it falls exactly on the off beat. I guess the length of this delay would be equal to 'high time' or 'low time' since that's half of the period.

If you just want a square wave that's half-a-wavelength out of phase, that's the same as 180 degrees out of phase - e.g. inverted. Instead of trying to delay it, just read the input state, and then output the inverse. It'll give you the same effect without the messing around.

That's a remarkably simple solution Tom, thank you. I think my lack of knowledge is causing me to really over complicate this.

So, with this very simple code i threw together it basically does what i want. I'm measuring the voltage from pin 8. It's at 5v because of the internal pull-up. when i touch pin 7 to 5v pin 8 goes to 0.06v. So that's all fine.

When i hook an LED up it's fairly dim, even with a 100ohm CLR. The voltage on pin 8 drops to 1.8v where it was 5v before. Seems strange.

I've just hooked up an LED from the stompLFO, placed it next to the one form pin 8 on the arduino and i think they're flashing perfectly in sync one after the other :)
I'm not even using any filtering now, it just started working and i have no idea what i did differently!

I wonder why i'm dropping so much voltage at the led though...


Here's where i'm at:
int input = 7;
int output = 8;
int inputState;



void setup() {
  pinMode (input, INPUT_PULLUP);
  pinMode (input, OUTPUT);
  Serial.begin (9600);


}

void loop() {

  inputState = digitalRead (input);
  if (inputState == LOW) {
    digitalWrite (output, HIGH);
  }

  if (inputState == HIGH) {
    digitalWrite (output, LOW);
   
  }

}

anotherjim

pinMode (input, OUTPUT);         ?

Don't you want...
pinMode (output, OUTPUT);        ?
...to set pin8 as output.

patrick398

Quote from: anotherjim on September 15, 2020, 04:05:02 PM
pinMode (input, OUTPUT);         ?

Don't you want...
pinMode (output, OUTPUT);        ?
...to set pin8 as output.

Crikey, what on earths going on here. Hang on i'll check that out

patrick398

#47
Ok thanks for that Jim, that seems to have been causing the LED brightness issue.

int input = 7;
int output = 8;
int inputState;

void setup() {
  pinMode (input, INPUT_PULLUP);
  pinMode (output, OUTPUT);
  Serial.begin (9600);
}

void loop() {
  inputState = digitalRead (input);
  if (inputState == LOW) {
    digitalWrite (output, HIGH);
  }

  if (inputState == HIGH) {
    digitalWrite (output, LOW);
   
  }

}


Which can be simplified to:
int input = 7;
int output = 8;
int inputState;



void setup() {
  pinMode (input, INPUT_PULLUP);
  pinMode (output, OUTPUT);
  Serial.begin (9600);


}

void loop() {

  digitalWrite(output, !digitalRead(input));
}



Given that this is now basically one line of code, can i do this on the same chip that is doing the bass drum trigger this thread was about originally, or will i still need an interrupt?

Thanks so much guys

patrick398

#48
Did some research on interrupts. I'm not sure what best practice is or whether this would screw something up, but i think i'm interrupting the main code every 100 milliseconds to execute the tempo read and write on off-beat section. Ignore the pin numbers for now, they're half arduino half attiny85, i'll sort that later.

What do you think?

//don't forget 10k pulldown on TRIGGER_IN

#include <TimerOne.h>

int TRIGGER_IN = 0; // ATtiny pin (5) connected to flip flop output
int TRIGGER_OUT = 1; // ATtiny pin (6) connected to bass drum trigger
int PULSE = 50; // Set trigger out pulse length as 50 ms
int triggerState = 0; // set variale for trigger state
int lastTriggerState = 0; //set variable for last trigger state
int tempoInput = 7;
int tempoOutput = 8;
int inputState;



void setup() {
  Timer1.initialize (100000);   // starting interrupt which will go off every ' 100,000 ' microseconds (100 milliseconds)
  Timer1.attachInterrupt (offBeat);
  pinMode (TRIGGER_IN, INPUT); // define TRIGGER_IN as an input (could try using just input_pullup)
  pinMode (TRIGGER_OUT, OUTPUT); // define TRIGGER_OUT as an output
  pinMode (tempoInput, INPUT);
  pinMode (tempoOutput, OUTPUT);
}



void loop() {


  int readValue = analogRead(2) * 3; // read pots value between 0 and 1023 and multiplies it by 3
  triggerState = digitalRead(TRIGGER_IN); // read the trigger in pin


  if (triggerState != lastTriggerState) { // is trigger state not equal to last trigger state
    if (triggerState == HIGH) { // if trigger state has changed...

      delay (readValue); // delay for period set by POT_PIN
      digitalWrite (TRIGGER_OUT, HIGH); // if it's high write TRIGGER_OUT high
      delay (PULSE);
    }

    lastTriggerState = triggerState;

    digitalWrite (TRIGGER_OUT, LOW); // if it's low write TRIGGER_OUT low
  }
}

void offBeat(){
  digitalWrite(tempoOutput, !digitalRead(tempoInput));
  return;
}


potul

This is a much simpler approach, it's a good idea to just invert the signal.

You can do this in the same microcontroller, and I don't think you need to do any interrupt. You just need to get rid of the delay() instruction, and instead just measure the time that passed since last check. This way the code will never stop.

Although interrupt might work as well.

patrick398

Yes very thankful to Tom for pointing out how much simpler it could be!
I have it working with the interrupt though i had to play with the interrupt timing. At 100000 microseconds it was working but i could detect a slight lag periodically one the LED indicating the 'off-beat'. I guess this was caused by the interrupt as changing the timing to 1000 seems to have sorted that.
Do you foresee any issues with this method?

Thanks again

ElectricDruid

Quote from: patrick398 on September 16, 2020, 05:19:20 AM
I have it working with the interrupt though i had to play with the interrupt timing. At 100000 microseconds it was working but i could detect a slight lag periodically one the LED indicating the 'off-beat'. I guess this was caused by the interrupt as changing the timing to 1000 seems to have sorted that.
Do you foresee any issues with this method?

No, interrupts are a *very* useful technique and you should use them! Especially if they're as simple to set up as they seem to be from your code - that's great! The early PICs I used didn't even include any context saving, so when you entered an interrupt you had to manually store anything important onto the stack for later, and then recover it all at the end of the interrupt routine. A right PITA.

I'm not surprised you shortened the interrupt period. 100msec is sssssllllllooooowwwww in uP terms. 1msec is still long enough for the chip to run (say) 8000 instructions, so it's not tight at that.


patrick398

Quote from: ElectricDruid on September 16, 2020, 06:13:20 AM

. 1msec is still long enough for the chip to run (say) 8000 instructions, so it's not tight at that.

Crikey, i don't think i've got my head around just how quick these things are yet!

Thanks for your help.

I'm yet to try this chip with the rest of the actual circuit its for yet so i doubt this will be the last you hear from me on the matter haha

patrick398

As i feared this doesn't quite work with the tap tempo circuit i'm trying to use it with. The tap tempo is someone elses, i have the chip, it's a PIC12F629, but i can't read any voltage spikes coming from it's output pin with my DMM and i can barely see the pulses on my oscope. The tap tempo does work though, i've hooked it up to a flip flop and it's flashing an LED.
I feel like i'm missing something critical here. Either the voltage spikes are two low for the attiny to detect a high state, or they're too quick? But i doubt that they're too quick somehow. I'm not really sure what to do now, it really doesn't help that i can't measure anything coming out of the tap tempo...
Is there something i'm missing? A reason why the attiny wouldn't be able to read the tap tempo chip?

Thanks...and sorry for all this arduino based misery lately

ElectricDruid

Some of us love a bit of uP-based misery! Makes such a change from all that analogue misery on the rest of this forum!

Could you modify the tap tempo code to *toggle* a pin instead of producing such a short pulse? Or is there a way you can find out what sets the timing of the pulse it outputs and make it longer?

It sounds like the Tap Tempo output pulse is only the very briefest spike and the input is simply not fast enough to catch it. You say you doubt they're too quick, but how quick are they exactly? You also say you can barely see them on an *osciiloscope* and that makes them sound pretty damn quick to me!

anotherjim

Try a small cap to ground on the tap pulse to act as a pulse stretcher -  probably no larger than 1nF. A simple bodge that can work, although it reduces the peak of the pulse, it will be wider and it doesn't have to reach 5v to be seen as high (normally >3v). Also you can enable pull-up on the input to make it a little easier to go high.


patrick398

Quote from: ElectricDruid on September 22, 2020, 06:23:02 PM
Some of us love a bit of uP-based misery! Makes such a change from all that analogue misery on the rest of this forum!
Ha yeah it's a nice change for me too, but bringing back a lot of painful memories from when i started trying to teach myself electronics...so much to learn, so little time!

Quote from: ElectricDruid on September 22, 2020, 06:23:02 PM
Could you modify the tap tempo code to *toggle* a pin instead of producing such a short pulse? Or is there a way you can find out what sets the timing of the pulse it outputs and make it longer?
The tap tempo is written by someone else, i've just been supplied the chip. It's a bit of a black box scenario.

Quote from: ElectricDruid on September 22, 2020, 06:23:02 PM
It sounds like the Tap Tempo output pulse is only the very briefest spike and the input is simply not fast enough to catch it. You say you doubt they're too quick, but how quick are they exactly? You also say you can barely see them on an *osciiloscope* and that makes them sound pretty damn quick to me!
Yeah you're right, it's super quick so probably too quick for the input. It also seems to be low voltage as well, but i'm having real difficulty measuring the thing.

Quote from: anotherjim on September 23, 2020, 11:21:04 AM
Try a small cap to ground on the tap pulse to act as a pulse stretcher -  probably no larger than 1nF. A simple bodge that can work, although it reduces the peak of the pulse, it will be wider and it doesn't have to reach 5v to be seen as high (normally >3v). Also you can enable pull-up on the input to make it a little easier to go high.
I seem to recall trying an RC filter on the output of the tap tempo but perhaps the resistor negated the effect of pulse stretching you're suggesting. I'll give it a try.

There is another possible solution i've overlooked which could potentially be a lot simpler. The tap tempo is triggering a kind of side chain which lights an LED on every beat the tap tempo is putting out. I could probably use this output, rather than the tap tempo itself, into the attiny85. I'm sorry i can't be more specific about the details, i'm trying to do this as a favour for someone and have only had a few glimpses of the schematic of the whole circuit. It seemed quite straight forward at first, but now you lot have been roped in ha.

The pulse from the side chain section has been described to me as looking like the top wave in this (childrens) picture i've drawn. The bottom wave is the expected output of the attiny, doing the inverse (off beat) The problem i see is that the rising edge of the 'off beat' won't fall in the middle of the first waves duty cycle, so won't actually be on the off beat.



The first and third pulses are triggering a 'bass drum', second and fourth a 'snare'. I'm trying trigger a 'high hat' on every off beat, but as i see it the off beat should fall exactly in the middle of two pulses, which it surely won't in this scenario.

I hope i'm making sense, this has got me in a pickle

potul

Unfortunately, Tom's proposal to just invert the input will only work if you have a square signal with 50% duty cycle, or similar. You got the point.
I see two options:
1-If you know well the waveform of the pulse, you can still use the inverting tip, but you would need to compensate with some delay in the response. This delay will not be fixed, most probably will have to be a function of the frequency. Not very convenient
2-Measure the peak to peak time (or edge to edge) (pretty easy using millis() ), and apply a delay of T/2. In this case, you go back to needing peak/edge detection.


patrick398

Yes i was thinking it would involve something like this. So i would achieve peak detection using state change?
I'm not sure how i would go about measuring the peak to peak time using millis()...my first thought was to use pulseIn to measure the high time, pulseIn to measure the low time, add them to get the peak to peak time and then divide that by two. Interested to know if its easier using millis() though

Thanks

potul

The issue with using PulseIn is that if I'm not wrong, it pauses execution until the pulse is done. This means that in order to do your full measure (High and LOW) you may have to wait more than one full cycle because the function needs 2 transitions to do the measure.
I will try later to draft some code for you on how to use states and millis() to do this in one shot.