Thought this concept might be useful for anyone wanting a variable-frequency oscillator :-
The anti-paralleled transistors in the optoisolators behave as a variable bi-polar current source to determine the oscillation frequency. Frequency is approximately linearly dependent on the photodiode input current, with a range of at least one decade for any given timing capacitor. U3a is configured as a Schmitt trigger with upper and lower thresholds as close to the rails as is reasonable (to maximise the triangle-wave amplitude), given that the opamp is not a rail-to-rail one. U3b is a unity gain buffer. The use of optoisolators naturally has the advantage that the frequency control can be floating with respect to the oscillator output if desired.
The el cheapo variant below uses one optoisolator in a diode bridge, but is otherwise similar. Its triangle wave-shape is kinked slightly due to the diodes.
I haven't investigated the upper frequency limit, effects of temperature or using alternative op-amps/optos.
Have fun.

The anti-paralleled transistors in the optoisolators behave as a variable bi-polar current source to determine the oscillation frequency. Frequency is approximately linearly dependent on the photodiode input current, with a range of at least one decade for any given timing capacitor. U3a is configured as a Schmitt trigger with upper and lower thresholds as close to the rails as is reasonable (to maximise the triangle-wave amplitude), given that the opamp is not a rail-to-rail one. U3b is a unity gain buffer. The use of optoisolators naturally has the advantage that the frequency control can be floating with respect to the oscillator output if desired.
The el cheapo variant below uses one optoisolator in a diode bridge, but is otherwise similar. Its triangle wave-shape is kinked slightly due to the diodes.

I haven't investigated the upper frequency limit, effects of temperature or using alternative op-amps/optos.
Have fun.