Well, Manipulate is a lexical scoping construct, like Module. Consider:
var = "global"; func[] := var; Module[{var = "local"}, func[]]
This correctly returns "global" and not "local", because the var scoped by the Module is different from any var outside the Module. See the lexical scoping docs for more information and examples.
The same goes for Manipulate. Your definition of f refers to the symbol b, but the b in the definition of f is not the same b as the b scoped by Manipulate. The definition of 'speed' doesn't refer to local Manipulate variables, so it doesn't have the scoping issues that f does.
As Simon suggested, one way to avoid this scoping problem would be to move the definition of f into the scoping construct. That works fine for Module, but can cause subtle problems for Manipulate. (For instance, if you had two copies of a Manipulate output, and each set f to be a function of local Manipulate variables, then f would be constantly redefined whenever you interact with either output.)
A solution which works better for Manipulate would be to pass local variables as arguments to your utility functions.
var = "global"; func[x_] := x; Module[{var = "local"}, func[var]]